gpt4 book ai didi

javascript - 当成功函数失败时,jQuery Ajax promise 队列不起作用

转载 作者:行者123 更新时间:2023-11-28 14:48:19 25 4
gpt4 key购买 nike

我有一个单页应用程序,它使用基于 promise 的排队机制,如下所示:

a) 处理ajax请求的函数

function AjaxSender(SomeAjaxData, FunctionToCallBack, SomeCallBackData) {

return $.ajax({
url: ...,
type: "POST",
data: SomeAjaxData,
success: function (msg, textStatus, request) {

if (FunctionToCallBack) {

FunctionToCallBack(SomeCallBackData);
//problem if there's a bug when this executes
}
}
});
}

b) 使用 Promise 对象对请求进行排队的函数

var AppAjaxPromise;    
function AjaxRequestQueue(SomeAjaxData, FunctionToCallBack, SomeCallBackData) {

if (AppAjaxPromise) {

AppAjaxPromise = AppAjaxPromise.then(function () {

return AjaxSender(SomeAjaxData, FunctionToCallBack, SomeCallBackData);
});

return AppAjaxPromise;
}

AppAjaxPromise = AjaxSender(SomeAjaxData, FunctionToCallBack, SomeCallBackData);

return AppAjaxPromise;
}

当我想发送ajax请求时,我调用AjaxRequestQueue(TheAjaxData, TheFunctionToCallBack, TheCallBackData)排队机制确保如果同时发送多个请求,或者在一个请求未返回之前,它们会在前一个请求完成后排队并处理。

当错误停止回调函数的执行时,就会出现问题。如果该函数出现错误,整个排队机制就会停止,并且调用 AjaxRequestQueue 不会再触发 ajax 请求。

我需要做什么来解决这个问题?

最佳答案

由于 jQuery 的 $.ajax 返回一个 promise (并且由于您正在使用它),请放弃使用 success 回调。而是在 then 回调中移动该代码。这将允许您链接一个 catch 方法 (jQuery 3.x) 调用它来响应错误。如果您没有在该 catch 回调中触发另一个错误,则它返回的 promise 将再次得到解析(而不是拒绝),因此链的其余部分不会被中止:

function ajaxSender(someAjaxData, functionToCallBack, someCallBackData) {
return $.ajax({
url: ...,
type: "POST",
data: someAjaxData
}).then(function (msg, textStatus, request) {
if (functionToCallBack) {
functionToCallBack(someCallBackData);
}
}).catch(function (err) {
console.log('error occurred, but request queue will not be interrupted', err);
});
}

jQuery 2.x

以上需要 jQuery 3.x。在 3.x 之前的 jQuery 版本中,您可以像这样替换 catch 方法(注意 null 参数):

       ...
}).then(null, function (err) {
...

...但 jQuery 2.x 的 promise 并非如此 Promise/A+合规性,这使得正确处理变得很痛苦。以下是如何为 jQuery 2.x 做到这一点。此代码段使用模拟延迟和 HTTP 响应状态代码的 URL,这允许它测试请求错误、JavaScript 运行时错误和排序:

function ajaxSender(someAjaxData, functionToCallBack, someCallBackData) {
return $.ajax({
// URL for demo: server will use the sleep parameter in the data,
// and will return the given HTTP status
url: "http://httpstat.us/" + someAjaxData.status,
type: "GET", // The demo URL needs a GET
data: someAjaxData
}).then(function (data) {
if (functionToCallBack) {
try { // Would not be necessary if jQuery 2.x were Promise/A+ compliant
functionToCallBack(someCallBackData);
} catch (e) {
console.log(someCallBackData, 'Error occurred during callback');
}
}
}, function (err) { // This second function captures ajax errors
console.log(someCallBackData, 'HTTP error');
// Return a resolved promise.
// This would not be necessary if jQuery 2.x were Promise/A+ compliant
return $.when();
}); // In jQuery 3.x you would chain a catch call here instead of the try/catch.
}

var appAjaxPromise = $.when();
function ajaxRequestQueue(someAjaxData, functionToCallBack, someCallBackData) {
appAjaxPromise = appAjaxPromise.then(function () {
return ajaxSender(someAjaxData, functionToCallBack, someCallBackData);
});
return appAjaxPromise;
}

// Demo: the ajax data argument is also used to define the HTTP response status and
// the sleep time, and the data argument identifies the number of the call

// Survive an HTTP error
ajaxRequestQueue({ status: 404, sleep: 1000 }, myCallBack, 1);
// Survive a runtime error in the callback
ajaxRequestQueue({ status: 200, sleep: 2000 }, myErrorGeneratingCallBack, 2);
// Demo that the callback calls remain in the right order
ajaxRequestQueue({ status: 200, sleep: 3000 }, myCallBack, 3);
ajaxRequestQueue({ status: 200, sleep: 2000 }, myCallBack, 4);
ajaxRequestQueue({ status: 200, sleep: 1000 }, myCallBack, 5);

function myCallBack(data) {
console.log(data, "My callback is called");
}
function myErrorGeneratingCallBack(data) {
console.log(data, "My callback is called");
throw "I threw an error in my callback";
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

当迁移到 jQuery 3 时,您仍然可以继续上述模式:它仍然有效。但理想情况下,您应该将代码迁移到我在顶部提供的基于 catch 的版本。

其他一些备注

人们一致认为,当变量是构造函数/类时,仅将其首字母大写。

通过将 appAjaxPromise 初始化为立即解决的 Promise,您可以避免代码重复:

var appAjaxPromise = $.when();    
function ajaxRequestQueue(someAjaxData, functionToCallBack, someCallBackData) {
appAjaxPromise = appAjaxPromise.then(function () {
return ajaxSender(someAjaxData, functionToCallBack, someCallBackData);
});
return appAjaxPromise;
}

关于javascript - 当成功函数失败时,jQuery Ajax promise 队列不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45536328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com