javascript - VanillaJS Promise 实现替换 jQuery 通知/进度事件
问题描述
我目前正在使用一个$.Deferred()
对象来发布消息。
当服务器返回错误时,我正在使用notify
,然后重试,直到成功或失败X
多次。
我想去掉 jQuery 的使用,ant 移到 ES6 相关选项。
我知道如何使用Promise()
,但它可以被拒绝或解决,但不能两者兼而有之。
有更好的主意吗?
当前代码:
var def = $.Deferred(),
data = {
iTries: 0,
....
};
$.ajax({
type: "POST",
url: "POST",
data: data,
timeout: 15000,
success: d => def.resolve(d);,
error: function(vSocket, status, error) {
def.notify('error'); // this I want to replace
data.iTries++;
//try again
if (data.iTries < 40) window.setTimeout(function() {
DoAgain(data, def).then(q => def.resolve(q));
}, 9000);
else {
def.reject();
}
}
else {
if (data.iTries < 20) window.setTimeout(function() {
Poll.AjaxPoll(data, def).then(q => def.resolve(q));
}, 30000);
}
}
});
解决方案
从您的代码看来,您正在使用 ES6(您正在使用箭头函数)。您可以使用 es6 箭头函数和承诺遵循递归方法,它可能是这样的:
doAjaxRequest(data) {
fireAPICall(data).then(response => { // fireAPICall is a method that fires the post request and returns the response received from server
if(response.status == 200) { // success (this if statement is optional)
// handle success
let d = response.data;
}
}).catch(error => { // failure
data.iTries++;
if(data.iTries < 40) {
window.setTimeout(() => {doAjaxRequest(data)}, 9000); // try again
} else if(data.iTries < 20) {
window.setTimeout(() => {doAjaxRequest(data)}, 30000); // try again
}
});
}
对于该fireAPICall
方法,您可以使用任何基于 Promise 的 http 客户端,例如axios或Fetch API,这里我使用的是axios
:
fireAPICall(data) {
return axios.post("url", data);
}
更新:如果您想同时处理reject/failure
事件和notify/progress
事件,这将需要一些服务器端协作。202
如果发生进度事件(尚未准备好),您可以让服务器返回状态代码(或任何其他更合适的状态代码),您可以在.then()
回调中处理它:
doAjaxRequest(data) {
fireAPICall(data).then(response => { // fireAPICall is a method that fires the post request and returns the response received from server
if(response.status === 202) { // notify/progress event
data.iTries++;
if(data.iTries < 40) {
window.setTimeout(() => {doAjaxRequest(data)}, 9000); // try again
} else if(data.iTries < 20) {
window.setTimeout(() => {doAjaxRequest(data)}, 30000); // try again
} else {
return Promise.reject('poll eneded with no success'); // exceeded maximum number of times for polling, so reject. This will invoke the catch callback method with this error
}
} else { // handle success
let d = response.data;
}
}).catch(error => { // reject/failure for some other reason
// handle error
});
}
推荐阅读
- html - 角度下拉验证
- mysql - 如何将由 TIME() 函数过滤的 mysql 查询转换为 laravel 查询生成器?
- python - 无法使用 discord.py 连接到主机
- c# - Dialogflow 读取响应流
- bash - 从 mac 自动在 telnet 中输入文本
- c++ - 查找 x^n 的所有组合,并检查它们加起来是否等于一个数字,不包括相同的数字
- php - 删除数组内的重复 ID
- filter - 如何对 React-Konva 中的元素应用模糊等填充器
- android - Firebase C++ VS2018 SDL2 - firebase::app::create(...) 出现异常
- ios - UICollectionView contentSize.width 是错误的