当管道破裂时如何处理AJAX响应?

前端之家收集整理的这篇文章主要介绍了当管道破裂时如何处理AJAX响应?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个( Spring Boot 1.5)REST服务器处理文件上传(multipart / form-data)和一个使用jQuery fileupload的JS客户端.在大多数情况下它工作正常,但是当我想上传一个更大的文件(大约4MB)时,服务器会发现它超出了限制并发回包含错误消息的响应.

但是,似乎服务器停止读取请求(当然是正确的),这导致客户端管道损坏.在这种情况下,不处理响应.使用以下data.jqXHR(data.response未定义)调用失败回调:

{"readyState":0,"responseText":"","status":0,"statusText":"error"}

使用curl进行调用时,结果为:

HTTP/1.1 200
Content-Type: application/json;charset=UTF-8

curl: (55) Send failure: Broken pipe
{"files":[{"size":3863407,"error":"upload_uploadSizeExceeded"}]}

因此返回了一个响应,但JS客户端似乎忽略了它.有没有选项让jQuery处理响应,即使请求只是部分发送?

BTW:更奇怪的是,我在服务器日志中看到这样的请求多次重复这种情况,也许是JS中的一种重试机制?

Is there any option to make jQuery handle the response even if the
request is sent only partially?

简答

不,浏览器使用XMLHttpRequest和Fetch API,这被规范视为网络错误,网络错误故意为空.

CURL不根据XMLHttpRequest规范处理响应.

答案很长

模拟服务器

阅读请求的ReadableStream并取消中途:

const http = require('http');

const server = http.createServer((req,res) => {
    res.setHeader('Access-Control-Allow-Origin','*');
    res.setHeader('Content-Type','text/plain');

    //Close Request ReadableStream Prematurely
    //to simulate close pipe on exceed file size
    if (req.url === '/data' && req.method === 'POST') {
        console.log('simulating...');

        let i = 0;
        req.on('data',chunk => {
            if (i++ === 10)
                req.destroy('broken pipe');
        });
    }

    res.end('fooby\n');
}).listen(8080);

客户测试

方法1:XMLHttpRequests

我仔细检查了每个事件,没有发送字节的指示.如果我们确实有一个Sent字节值,应该加载,我们可以知道请求是否在中途被取消以处理这种情况而没有响应:

let req = new XMLHttpRequest();
req.open('POST','http://localhost:8080/data');
    req.onloadstart = function (event) {
            console.log(event);
    };
    req.onprogress = function (event) {
            console.log(event);
    };
    req.onabort = function (event) {
            console.log(event);
    };
    req.onerror = function (event) {
            console.log(event);
    };
    req.onload = function (event) {
            console.log(event);
    };
    req.ontimeout = function (event) {
            console.log(event);
    };
    req.onloadend = function (event) {
            console.log(event);
    };
    req.onreadystatechange = function (event) {
            console.log(event);
    };
req.send(new ArrayBuffer(100000000));

不幸的是,没有.

The read-only XMLHttpRequest.status property returns the numerical
status code of the response of the XMLHttpRequest. status will be an
unsigned short. Before the request is complete,the value of status
will be 0. It is worth noting that browsers report a status of 0 in
case of XMLHttpRequest errors too.

XMLHttpRequest specification

A response whose type is “error” is known as a network error.

A network error is a response whose status is always 0,status message
is always the empty byte sequence,header list is always empty,body
is always null,and trailer is always empty.

方法2:获取API

我希望拦截一个低级别的ReadableStream并得到一些东西,但不幸的是,没有调用网络错误解决回调:

fetch('http://localhost:8080/data',{
        method: 'POST',body: new ArrayBuffer(100000000),mode: 'cors'
}).then(resp => {
        console.log(resp);
        //hopefully we can get readable stream here
        //...nope,networkerrors do not trigger resolve
}).catch(error => {
        console.log(error);//TypeError: "NetworkError when attempting to fetch resource."
}).then(retry => {
        console.log(retry);
});

A fetch() promise rejects with a TypeError when a network error is
encountered
,although this usually means a permissions issue or
similar. An accurate check for a successful fetch() would include
checking that the promise resolved,then checking that the Response.ok
property has a value of true. An HTTP status of 404 does not
constitute a network error.

Fetch Documentation

Fetch Specification

浏览器不会将此视为HTTP错误,而是网络错误,因此不会转发与用户代码相关的任何HTTP.

结论

XHR和Fetch规范声明网络错误作为空响应处理.

猜你在找的Ajax相关文章