我正在尝试以特定方式使用angularjs异步实现JavaScript函数,如下图所示。
我尝试了几个没有运气的选项http://jsfiddle.net/pb53cafy/4/
示例代码:
function PromiseCtrl($scope, $q, $timeout) {
//
var Afunction = function() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve("Success A");
}, 1000);
return deferred.promise;
};
var Bfunction = function() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve("Success B");
}, 2000);
return deferred.promise;
};
$scope.result = "Waiting";
$q.all([
Afunction(),
Bfunction()
]).then(function(value) {
$scope.result = value;
}, function(reason) {
$scope.result = reason;
});
//Remaining code ...
}
感谢您对此的帮助
编辑:使用我正在寻找的代码修改http://jsfiddle.net/pb53cafy/11/
答案 0 :(得分:2)
由于你总是想在A完成时继续,只需等待A,而不是等待B。
你还没有说B是什么,但是:
#1的例子:
var a = Afunction();
var b = Bfunction();
a.catch(function() {
return b; // A failed, chain to B
}).then(function(value) {
// ...rest of code...
$scope.result = value;
}, function(reason) {
$scope.result = reason;
});
#2的例子:
var a = Afunction();
var b = Bfunction();
a.then(function(value) {
// ...rest of code...
// We're at the point we need b
return b.then(function() {
// ...possibly more code here...
$scope.result = value;
});
}, function(reason) {
$scope.result = reason;
});
在这两种情况下,我都提到了首先启动A(如果您正在执行类似HTTP请求的事情,这可能很重要)。如果这不重要,您可以摆脱a
变量。
答案 1 :(得分:2)
我强烈建议您回答评论中提出的问题。没有这些,很难给你很好的建议。
但是,假设你想要B 的结果,当它在A 之前可用时可以没有它,那么你可以这样做:
$scope.result = "Waiting";
var bResult = null;
var pa = Afunction();
var pb = Bfunction();
pb.then(function (br) {
bResult = br;
});
pa.then(function (ar) {
// if B finished first, its value will be in the
// bResult closure variable.
// if A finished first, bResult will be null.
$scope.result = ar;
}, function(reason) {
$scope.result = reason;
});
答案 2 :(得分:2)
您可以创建另一个函数来控制执行过程:
function execute() {
var deferred = $q.defer();
var bFinished;
var aPromise = Afunction().then(function(aRes) {
if(!bFinished) deferred.resolve(aRes);
return aRes;
}).catch(deferred.reject);
Bfunction().then(function(bRes) {
bFinished = true;
return aPromise.then(function(aRes) {
deferred.resolve(bRes + " and " + aRes);
});
});
return deferred.promise;
}
如果A先完成,它就不会等待B.
如果B先完成,它也会等待A完成。
答案 3 :(得分:1)
我将从ES Promise的角度回答您的问题,但您也可以将其调整为延迟。
解决类似任务的三个基本原语是:
Promise.all
采用可迭代的承诺并等待所有这些承诺解决或让其中任何一个拒绝。此原语将所有输入承诺视为相等,但这不是您的情况,A
和B
具有不同的含义。但是,请注意它在拒绝案件中是如何运作的。settle all
是Promise.all
的非标准类似物,它等待所有拒绝和解决(与前一个相矛盾)。它还将所有输入承诺视为相等。Promise.race
等待首先解决或拒绝。同时将所有输入视为相等。这个与你的情况最相似,请注意它是如何处理拒绝的。看起来你的案例中的A
输入比B
更重要,所以我们不能使用任何“对称”原语,我们需要一些手写的原语到resque。 / p>
// first, let's invoke both A and B producers,
// because we need parallel execution
var p_a = AFunction(…)
var p_b = BFunction(…)
// if p_b resolves earlier, we can save it
var shared_b
p_b.then(value => shared_b = value)
// because A is more like a leader, let's wait for it,
// we can't proceed without it in both scenarios,
// we can't use `all` or `race`
var p_pair = p_a.then(value =>
{
return [ value, shared_b ]
})
p_pair.then(([a, b]) =>
{
console.log(a, ': A is always here')
console.log(b, ': B only if was ready fast enough')
})
p_pair
现在是Promise<[ A, B | undefined ]>
。
B
拒绝被忽略。
您可以采用简单的方式将其调整为延迟,例如AFunction
和BFunction
。