如何轮询 API 作为 $.Deferred() 的一部分
How to poll an API as part of a $.Deferred()
下面的非功能性示例应该可以解释我正在尝试做什么,我只是不明白我需要使用什么模式来完成它。我尝试使用谷歌搜索来了解轮询和延迟,但找不到任何我能理解的内容。
我有一个轮询 API 的函数,我想等待该轮询 return 预期结果(等待端点指示某些内容已更改),然后再继续我的操作主功能。我做错了什么?
编辑:我应该补充一点,SEEMS 在下面的代码中出错的地方是,即使 deferred.resolve()
最终被调用,它似乎与 deferred
不一样24=]ed,所以 when
永远不会在 main()
中被激活。我猜它与超时有关,这意味着 deferred
在第一次重复时被破坏。无论如何,这是我的假设。
function pollAPI() {
var deferred = $.Deferred();
$.ajax({
url: url,
contentType: 'application/JSON',
method: 'GET'
}).done(function(data){
if (!desiredResult) {
setTimeout(function() {
pollAPI();
}, 1000);
} else {
deferred.resolve();
}
}).error(deferred.reject());
return deferred.promise();
}
function main() {
$.when(pollAPI()).then(function() {
// do something now that the API has returned the expected result
});
您可以使用对 pollAPI()
函数的后续调用的链接来创建一个具有其他链接的承诺。那会像这样工作:
// utility function to create a promise that is resolved after a delay
$.promiseDelay = function(t) {
return $.Deferred(function(def) {
setTimeout(def.resolve, t);
}).promise();
}
function pollAPI() {
return $.ajax({
url: url,
contentType: 'application/JSON',
method: 'GET'
}).then(function(data) {
// some logic here to test if we have desired result
if (!desiredResult) {
// chain the next promise onto it after a delay
return $.promiseDelay(1000).then(pollAPI);
} else {
// return resolved value
return someValue;
}
});
}
function main() {
pollAPI().then(function(result) {
// got desired result here
}, function(err) {
// ended with an error here
});
}
这有以下好处:
- 没有创建不必要的承诺来尝试包围已经有承诺的 ajax 调用。这避免了 common promise anti-patterns.
之一
- 对 API 的后续调用只是链接到原始承诺。
- 当你只有一个承诺时,不需要使用
$.when()
。你可以直接在上面使用 .then()
。
- 所有错误都会自动回溯到最初的承诺。
- 这使用了 ES6 标准
.then()
(实际上它在 jQuery 3.x 中变得更加合法标准 - 虽然它在 jQuery 1.x 中有效并且2.x 有它自己的非标准怪癖)这使得这个逻辑与其他产生承诺的异步函数更兼容。
此外,这里还有一些其他的重试想法:
下面的非功能性示例应该可以解释我正在尝试做什么,我只是不明白我需要使用什么模式来完成它。我尝试使用谷歌搜索来了解轮询和延迟,但找不到任何我能理解的内容。
我有一个轮询 API 的函数,我想等待该轮询 return 预期结果(等待端点指示某些内容已更改),然后再继续我的操作主功能。我做错了什么?
编辑:我应该补充一点,SEEMS 在下面的代码中出错的地方是,即使 deferred.resolve()
最终被调用,它似乎与 deferred
不一样24=]ed,所以 when
永远不会在 main()
中被激活。我猜它与超时有关,这意味着 deferred
在第一次重复时被破坏。无论如何,这是我的假设。
function pollAPI() {
var deferred = $.Deferred();
$.ajax({
url: url,
contentType: 'application/JSON',
method: 'GET'
}).done(function(data){
if (!desiredResult) {
setTimeout(function() {
pollAPI();
}, 1000);
} else {
deferred.resolve();
}
}).error(deferred.reject());
return deferred.promise();
}
function main() {
$.when(pollAPI()).then(function() {
// do something now that the API has returned the expected result
});
您可以使用对 pollAPI()
函数的后续调用的链接来创建一个具有其他链接的承诺。那会像这样工作:
// utility function to create a promise that is resolved after a delay
$.promiseDelay = function(t) {
return $.Deferred(function(def) {
setTimeout(def.resolve, t);
}).promise();
}
function pollAPI() {
return $.ajax({
url: url,
contentType: 'application/JSON',
method: 'GET'
}).then(function(data) {
// some logic here to test if we have desired result
if (!desiredResult) {
// chain the next promise onto it after a delay
return $.promiseDelay(1000).then(pollAPI);
} else {
// return resolved value
return someValue;
}
});
}
function main() {
pollAPI().then(function(result) {
// got desired result here
}, function(err) {
// ended with an error here
});
}
这有以下好处:
- 没有创建不必要的承诺来尝试包围已经有承诺的 ajax 调用。这避免了 common promise anti-patterns. 之一
- 对 API 的后续调用只是链接到原始承诺。
- 当你只有一个承诺时,不需要使用
$.when()
。你可以直接在上面使用.then()
。 - 所有错误都会自动回溯到最初的承诺。
- 这使用了 ES6 标准
.then()
(实际上它在 jQuery 3.x 中变得更加合法标准 - 虽然它在 jQuery 1.x 中有效并且2.x 有它自己的非标准怪癖)这使得这个逻辑与其他产生承诺的异步函数更兼容。
此外,这里还有一些其他的重试想法: