『设计』ES6原生实战Uploader工具类(从设计到实现)( 四 )

  • onprogress事件:根据返回的事件 , 计算好百分比 , 响应外部onprogress事件
    1. 因为xhr的返回格式不太友好 , 我们需要额外编写两个函数处理http响应:parseSuccess、parseError
    _post (file) {if (!file.rawFile) returnconst { headers, data, withCredentials } = this.settingconst xhr = new XMLHttpRequest()const formData = http://news.hoteastday.com/a/new FormData()formData.append('file', file.rawFile, file.fileName)Object.keys(data).forEach(key => {formData.append(key, data[key])})Object.keys(headers).forEach(key => {xhr.setRequestHeader(key, headers[key])})file.status = 'uploading'xhr.withCredentials = !!withCredentialsxhr.onload = () => {/* 处理响应 */if (xhr.status < 200 || xhr.status >= 300) {file.status = 'error'this._callHook('error', parseError(xhr), file, this.uploadFiles)} else {file.status = 'success'this._callHook('success', parseSuccess(xhr), file, this.uploadFiles)}}xhr.onerror = e => {/* 处理失败 */file.status = 'error'this._callHook('error', parseError(xhr), file, this.uploadFiles)}xhr.upload.onprogress = e => {/* 处理上传进度 */const { total, loaded } = ee.percent = total > 0 ? loaded / total * 100 : 0this._callHook('progress', e, file, this.uploadFiles)}xhr.open('post', this.setting.url, true)xhr.send(formData)} parseSuccess 将响应体尝试JSON反序列化 , 失败的话再返回原样文本
    const parseSuccess = xhr => {let response = xhr.responseTextif (response) {try {return JSON.parse(response)} catch (error) {}}return response} parseError 同样的 , JSON反序列化 , 此处还要抛出个错误 , 记录错误信息 。
    const parseError = xhr => {let msg = ''let { responseText, responseType, status, statusText } = xhrif (!responseText && responseType === 'text') {try {msg = JSON.parse(responseText)} catch (error) {msg = responseText}} else {msg = `${status} ${statusText}`}const err = new Error(msg)err.status = statusreturn err} 至此 , 一个完整的Upload类已经构造完成 , 整合下来大概200行代码多点 , 由于篇幅问题 , 完整的代码已放在个人github里 。
    测试与实践 写好一个类 , 当然是上手实践一下 , 由于测试代码并不是本文关键 , 所以采用截图的方式呈现 。 为了呈现良好的效果 , 把chrome里的network调成自定义降速 , 并在测试失败重传时 , 关闭网络 。
    『设计』ES6原生实战Uploader工具类(从设计到实现)
    本文插图
    服务端 这里用node搭建了一个小的http服务器 , 用multiparty处理文件接收 。
    『设计』ES6原生实战Uploader工具类(从设计到实现)
    本文插图
    客户端 简单的用html结合vue实现了一下 , 会发现将业务代码跟基础代码分开实现后 , 简洁明了不少
    『设计』ES6原生实战Uploader工具类(从设计到实现)
    本文插图
    拓展拖拽上传 拖拽上传注意两个事情就是
    1. 监听drop事件 , 获取e.dataTransfer.files
    2. 监听dragover事件 , 并执行preventDefault() , 防止浏览器弹窗 。
    更改客户端代码如下:
    『设计』ES6原生实战Uploader工具类(从设计到实现)