简体   繁体   English

如果XHR响应是一个ArrayBuffer表示具有error属性的JSON对象,则jQuery .ajax()调用error函数而不是成功函数

[英]jQuery .ajax() calls the error function instead of success if the XHR response is an ArrayBuffer representing a JSON object with an error property

Context: I'm trying to implement an ajax download with a progress bar and error handling. 上下文:我正在尝试通过进度条和错误处理来实现Ajax下载。 The front end makes a request to a backend which responds with either a file to download, or an error in the form of a JSON object. 前端向后端发出请求,后端以下载文件或JSON对象形式的错误作为响应。

Problem: I'm using a custom xhr, where the responseType is set to arraybuffer . 问题:我使用的是自定义xhr,其中responseType设置为arraybuffer This allows me to create a Blob for the file which I then use to present the download. 这使我可以为文件创建一个Blob,然后将其用于显示下载内容。 If the backend responds with a JSON object, I can detect it properly, convert it to a string, and parse it into a native Object . 如果后端使用JSON对象响应,我可以正确地检测到它,将其转换为字符串,然后将其解析为本地Object However, if that Object contains a property called error , which I use throughout my application, jQuery calls error() rather than success() , and passes one parameter, the value of the error property. 但是,如果该Object包含一个名为error的属性,我将在整个应用程序中使用它,则jQuery调用error()而不是success() ,并传递一个参数,即error属性的值。

What the heck is going on? 到底他妈发生了什么? I've set dataType: false to avoid any processing of data, but it seems that jQuery is parsing the arraybuffer, despite the dataType setting and the response header being set to application/octet-stream , and deciding that the object, having an error property, requires the error() function to be called. 我已将dataType: false设置为避免对数据进行任何处理,但是尽管dataType设置和响应标头设置为application/octet-stream ,并且确定该对象有错误,但jQuery似乎正在解析arraybuffer。属性,需要调用error()函数。

How can I avoid this behavior without changing my backend? 如何在不更改后端的情况下避免这种行为? An alternate implementation could be to leave the responseType as text, and then turn the text into a Blob when its a file, but I could never get that to work properly. 另一种实现方式可以是将responseType保留为文本,然后在文本成为文件时将其转换为Blob,但我永远无法使其正常工作。

$.ajax({
            url: "?download",
            method: "POST",
            data: {path: this.path, names: names},
            dataType: false,
            xhr: function() {
                var myXhr = $.ajaxSettings.xhr();
                myXhr.responseType = "arraybuffer"
                myXhr.addEventListener("progress", function(e) {
                    if (e.lengthComputable) {
                        var percent = Math.round(e.loaded / e.total * 100);
                        var text = dir.formatSize(e.loaded, true) + "/" + dir.formatSize(e.total, true)
                        $("#dl-progress-bar").css("width", percent + "%");
                        $("#dl-progress-text").text(text)
                    }
                })
                return myXhr;
            },
            success: function(data) {
                $("#dl-progress").hide()
                $("#dl-progress-bar").css("width", "0")
                $("#dl-progress-text").html(" ")
                var bufView = new Uint8Array(data);
                //Check if the arraybuffer is actually JSON, starting with {"
                if (bufView[0] == 123 && bufView[1] == 34 && bufView.length < 200) {
                    var string = decodeURIComponent(escape(String.fromCharCode.apply(null, Array.prototype.slice.apply(bufView))))
                    try {
                        var json = JSON.parse(string)
                        if (json.success === false && json.error) {
                            this.error(json.error)
                            return
                        }
                    }
                    catch (e) {}
                }


                if (data != null && navigator.msSaveBlob)
                    return navigator.msSaveBlob(new Blob([data], { type: type }), name)
                var a = $("<a style='display: none;'/>")
                var blob = new Blob([data], {type: "application/octet-stream"})
                var url = window.URL.createObjectURL(blob)
                a.attr("href", url)
                a.attr("download", filename)
                $("body").append(a)
                a[0].click()
                setTimeout(function() {
                    window.URL.revokeObjectURL(url);
                    a.remove()
                }, 0)
            },
            error: function(req, status, error) {
                debugger
                $("#dl-progress").hide()
                $("#dl-progress-bar").css("width", "0")
                $("#dl-progress-text").html("&nbsp;")
                this.ajaxError(req, status, error)
            }.bind(this)
        })

问题是我没有bind()我的成功函数,所以它调用了xhr对象的this.error()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 jQuery ajax() 在成功时将 json 对象返回给另一个函数会导致错误 - jQuery ajax() returning json object to another function on success causes error ajax中的服务器响应是错误功能而不是成功 - server response in ajax goes in error function instead of success 当响应json对象数据计数为零时,ajax成功回调函数将重定向到错误回调 - ajax success callback function redirects to error callback when response json object data count is zero AJAX 正在运行错误函数而不是成功函数 - AJAX is running error function instead of success function jQuery.ajax:TypeError:对象#的属性“ xhr” <Object> 不是功能 - jQuery.ajax: TypeError: Property 'xhr' of object #<Object> is not a function ajax使用多个调用覆盖XHR对象-jQuery - ajax is overwriting XHR object with multiple calls - jQuery Ajax成功和错误功能无法在jQuery中正确调用 - Ajax success and error function is not calling properly in jquery AJAX / JQuery成功:/ error:函数操作 - AJAX/JQuery success:/error: function manipulation 错误 xhr.abort() 不是 function 使用 Ajax jQuery - Error xhr.abort() is not a function using Ajax jQuery jQuery $ .ajax使用JSONP调用跨域,返回状态200,但是错误函数被调用而不是成功 - jQuery $.ajax call for cross domain with JSONP, returns status 200, but error function is being called instead of success
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM