所以我有一个情况,我有多个长度未知的承诺链。我希望在处理完所有 CHAINS 后运行一些操作。这可能吗?这是一个例子:
app.controller('MainCtrl', function($scope, $q, $timeout) {
var one = $q.defer();
var two = $q.defer();
var three = $q.defer();
var all = $q.all([one.promise, two.promise, three.promise]);
all.then(allSuccess);
function success(data) {
console.log(data);
return data + "Chained";
}
function allSuccess(){
console.log("ALL PROMISES RESOLVED")
}
one.promise.then(success).then(success);
two.promise.then(success);
three.promise.then(success).then(success).then(success);
$timeout(function () {
one.resolve("one done");
}, Math.random() * 1000);
$timeout(function () {
two.resolve("two done");
}, Math.random() * 1000);
$timeout(function () {
three.resolve("three done");
}, Math.random() * 1000);
});
在这个例子中,我为承诺一、二和三设置了一个
$q.all()
,它们将在某个随机时间得到解决。然后我将承诺添加到一和三的末端。我希望 all
在所有链条都已解决后解决。这是我运行这段代码时的输出:
one done
one doneChained
two done
three done
ALL PROMISES RESOLVED
three doneChained
three doneChainedChained
有没有办法等待链条解决?
我希望所有链条都解决后,所有问题都解决。
当然,那么只需将每个链的承诺传递给
all()
而不是最初的承诺:
$q.all([one.promise, two.promise, three.promise]).then(function() {
console.log("ALL INITIAL PROMISES RESOLVED");
});
var onechain = one.promise.then(success).then(success),
twochain = two.promise.then(success),
threechain = three.promise.then(success).then(success).then(success);
$q.all([onechain, twochain, threechain]).then(function() {
console.log("ALL PROMISES RESOLVED");
});
接受的答案是正确的。我想提供一个例子来向那些不熟悉
promise
的人详细说明。
例子:
在我的示例中,如果可用,我需要在呈现内容之前用不同的镜像 url 替换
src
标签的 img
属性。
var img_tags = content.querySelectorAll('img');
function checkMirrorAvailability(url) {
// blah blah
return promise;
}
function changeSrc(success, y, response) {
if (success === true) {
img_tags[y].setAttribute('src', response.mirror_url);
}
else {
console.log('No mirrors for: ' + img_tags[y].getAttribute('src'));
}
}
var promise_array = [];
for (var y = 0; y < img_tags.length; y++) {
var img_src = img_tags[y].getAttribute('src');
promise_array.push(
checkMirrorAvailability(img_src)
.then(
// a callback function only accept ONE argument.
// Here, we use `.bind` to pass additional arguments to the
// callback function (changeSrc).
// successCallback
changeSrc.bind(null, true, y),
// errorCallback
changeSrc.bind(null, false, y)
)
);
}
$q.all(promise_array)
.then(
function() {
console.log('all promises have returned with either success or failure!');
render(content);
}
// We don't need an errorCallback function here, because above we handled
// all errors.
);
解释:
来自 AngularJS docs:
then
方法:
then(successCallback, errorCallback, notifyCallback) – 无论承诺何时被解决或拒绝,然后调用 一旦成功或错误回调之一异步 结果可用。回调是用 single 调用的 argument:结果或拒绝原因。
$q.all(承诺)
将多个承诺组合成一个承诺,当 所有输入承诺都已解决。
promises
参数可以是一系列承诺。
关于
bind()
,更多信息在这里:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
最近遇到了这个问题,但承诺数量未知。使用 jQuery.map().
解决了function methodThatChainsPromises(args) {
//var args = [
// 'myArg1',
// 'myArg2',
// 'myArg3',
//];
var deferred = $q.defer();
var chain = args.map(methodThatTakeArgAndReturnsPromise);
$q.all(chain)
.then(function () {
$log.debug('All promises have been resolved.');
deferred.resolve();
})
.catch(function () {
$log.debug('One or more promises failed.');
deferred.reject();
});
return deferred.promise;
}
您可以在“异步函数”中使用“等待”。
app.controller('MainCtrl', async function($scope, $q, $timeout) {
...
var all = await $q.all([one.promise, two.promise, three.promise]);
...
}
注意:我不是 100% 确定您可以从非异步函数调用异步函数并获得正确的结果。
也就是说,这永远不会在网站上使用。但是对于负载测试/集成测试......也许吧。
示例代码:
async function waitForIt(printMe) {
console.log(printMe);
console.log("..."+await req());
console.log("Legendary!")
}
function req() {
var promise = new Promise(resolve => {
setTimeout(() => {
resolve("DARY!");
}, 2000);
});
return promise;
}
waitForIt("Legen-Wait For It");
我在 ocLazyLoad 库中使用了这个例子:
var promises = [];
angular.forEach(paths, function loading(path) {
promises.push(buildElement('css', path, params));
});
$q.all(promises).then(function success() {
callback();
}, function error(err) {
callback(err);
});