【问题标题】:XMLHttp​Request​.upload.onprogress is triggered when server respons 500 error服务器响应 500 错误时触发 XMLHttp​Request​.upload.onprogress
【发布时间】:2019-10-17 10:16:26
【问题描述】:

我使用XMLHttp​Request 上传文件。如果服务器响应错误消息 500,我会尝试在 onprogress 事件之前处理错误消息。

XMLHttpRequest

const xhr = new XMLHttpRequest();

      xhr.onreadystatechange = function (oEvent) {
        if (xhr.readyState === 4) {
            if (xhr.status === 500) {
              console.log('error2');
            }
        }
    };

    xhr.onload = function() {
      if (this.status == 200) {
        console.log('success');
      }
    };

      xhr.upload.onprogress = function(e) {
        if (e.lengthComputable) {
          var percentComplete = (e.loaded / e.total) * 100;
          console.log(percentComplete);
        }
      };

      xhr.open("POST", "http://127.0.0.1:1337/upload-file", true);
      var formData = new FormData();
      formData.append("file", e.file);
      xhr.send(formData);

我故意在服务器上抛出错误消息:

const Koa = require('koa');
const Router = require('koa-router');
const cors = require('@koa/cors');
const serve = require('koa-static');
const path = require('path');
const koaBodyMultipart = require('koa-body')({ multipart: true });

const app = new Koa();
app.use(cors());
app.use(serve(path.join(process.env.PWD, '/dist')));

const router = new Router();

router
  .post('/upload-file', koaBodyMultipart, (ctx, next) => {
    const { file } = ctx.request.files;
    // if (file) {
    //     ctx.response.body = 'ok';
    // } else {
    //     ctx.throw(500,'Error Message');
    // }
    ctx.throw(500,'Error Message');
  });

app.use(router.routes()).use(router.allowedMethods());

// don't listen to this port if the app is required from a test script
if (!module.parent) {
  var server = app.listen(process.env.PORT || 1337);
  var port = server.address().port;
  console.log('running at port:' + port)
}

为什么upload.onprogressxhr.onreadystatechangexhr.onload 之前触发?如何在显示上传进度之前显示错误消息?

【问题讨论】:

标签: javascript ajax http xmlhttprequest


【解决方案1】:

我编写了一个简单的脚本来检查事件的顺序。事件的顺序总是这样发生:

readystateChange: 1
loadstart
XHR OPTIONS http://127.0.0.1:1337/upload-file [HTTP/1.1 204 No Content 24ms]
XHR POST http://127.0.0.1:1337/upload-file [HTTP/1.1 500 Internal Server Error 20ms]
progress
load
loadend
readystateChange: 2
readystateChange: 3
readystateChange: 4

Progress 事件总是在load 事件之前触发。

由于在显示错误消息之前会更新进度,因此您可以将进度更新到某个百分比,例如 95%。然后在loadendreadyStateChange 事件中处理其余的更新。例如:

xhr.upload.onprogress = function(e) {
    if (e.lengthComputable) {
        var percentComplete = (e.loaded - e.total*0.05 / e.total) * 100;
        percentComplete = percentComplete < 0? 0: percentComplete;
        console.log(percentComplete);
    }
};

xhr.onreadystatechange = function (oEvent) {
    if (xhr.readyState === 4) {
        if (xhr.status === 500) {
            // Handle error case
        } else if (xhr.status === 200){
            percentComplete = 100;
        }
    }
};

【讨论】:

  • 感谢您的回复。这总比没有好,但我仍然认为在触发onprogress 事件之前无法处理服务器错误真的很奇怪。如果没有更好的答案,我会奖励你的答案。
【解决方案2】:

根据XMLHttpRequest Level 2 - Determinate if upload finished

progress 在发送和接收数据时被调用,这就是当你发送文件时发生的事情,即使响应是错误的。 state changed 事件仅在所有完成并且服务器关闭连接后才会触发。

【讨论】:

  • 感谢您的回答。我试图在各种 xhr 事件处理程序中处理 xhr.status === 500,但我无法在 onprogress 事件之前获得错误状态:/
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
  • 1970-01-01
  • 2020-04-29
  • 1970-01-01
  • 1970-01-01
  • 2020-06-30
  • 1970-01-01
相关资源
最近更新 更多