簡體   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

上下文:我正在嘗試通過進度條和錯誤處理來實現Ajax下載。 前端向后端發出請求,后端以下載文件或JSON對象形式的錯誤作為響應。

問題:我使用的是自定義xhr,其中responseType設置為arraybuffer 這使我可以為文件創建一個Blob,然后將其用於顯示下載內容。 如果后端使用JSON對象響應,我可以正確地檢測到它,將其轉換為字符串,然后將其解析為本地Object 但是,如果該Object包含一個名為error的屬性,我將在整個應用程序中使用它,則jQuery調用error()而不是success() ,並傳遞一個參數,即error屬性的值。

到底他媽發生了什么? 我已將dataType: false設置為避免對數據進行任何處理,但是盡管dataType設置和響應標頭設置為application/octet-stream ,並且確定該對象有錯誤,但jQuery似乎正在解析arraybuffer。屬性,需要調用error()函數。

如何在不更改后端的情況下避免這種行為? 另一種實現方式可以是將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM