我需要这样做:浏览器必须向服务器发出N个请求,请求不能是异步的,下一个请求在先前的请求停止后开始。
我可以用function A
写一些for i < N i++
并再次递归调用此function A
来执行此操作,但它根本不是很漂亮。此外,这称为回调地狱。我想要一些更美丽的解决方案。
我找到了deffered
个对象。有人说,它可以帮助我摆脱回调地狱。我想要这样的东西。 setTimeout
模仿一个异步请求:
function foo1(some) {
debugger;
setTimeout(function foo1async() {
debugger;
deffered.resolve();
}, 500);
return deffered.promise;
}
function foo2(some) {
debugger;
setTimeout(function foo2async() {
debugger;
deffered.reject();
}, 500);
return deffered.promise;
}
function foo3() {
debugger;
setTimeout(function foo3async() {
debugger;
deffered.resolve();
}, 500);
return deffered.promise;
}
var deffered;
function doChain() {
debugger;
deffered = $q.defer();
var promise = deffered.promise;
promise.then(foo1);
promise.then(foo2);
promise.then(foo3);
promise["finally"](function () {
debugger;
});
deffered.resolve();
}
foo2
,然后调用foo2async
。
3.现在我预计,foo3
不会开始,因为foo2async
会拒绝被拒绝。之后,我希望在finally
部分中调用foo。实际上,我有这个:
foo1
,foo2
和foo3
被调用。然后调用finally
部分中的foo。然后调用foo1async
,foo2async
和foo3async
个函数。
我如何能得到我期待的东西?
实际上,我会有这样的事情:
for(var i = 0; i < N; i++) {
(function (iter) {
promise.then(function () {
foo(iter);
});
})(i);
}
答案 0 :(得分:1)
你在这里遇到了一些问题。
首先,您使用延迟将基于回调的异步函数转换为基于承诺的函数 - 但每个函数都需要自己的deferred.promise
,因此需要自己的deferred
。实际上,我更喜欢使用$q
构造函数:
function fooN(input){
return $q(function(resolve, reject){
setTimeout(function(){
resolve(input + "; some more data");
}, 500);
});
}
(您也可以使用var deferred = $q.defer()
)
fooN
现在返回一个承诺,因此您不再需要使用$q.defer()
。
事实上,如果异步函数已经基于承诺,例如$timeout
或$http
,那么您根本不需要deferred
,例如:
function fooN(input){
return $timeout(function(){
return input + "; some more data";
}, 500);
})
所以,我们假设foo1
,foo2
和foo3
的实现方式与fooN
一样 - 所有返回的承诺。
要使顺序调用,您需要链接promises - 而不是将多个处理程序附加到某个根承诺。
我会为你分解:
function doChain(){
var foo1Promise = foo1();
var foo2AfterFoo1Promise = foo1Promise.then(foo2);
var foo3AfterFoo2Promise = foo2AfterFoo1Promise.then(foo3);
var promise = foo3AfterFoo2Promise.then(function(finalData){
return doSomeProcessing(finalData); // if needed
});
promise.catch(function(error){
// "rethrow", if can't handle
return $q.reject({msg: "Some error occurred"});
})
return promise;
}
或者,同样,更简洁:
function doChain(p){
return foo1(p)
.then(foo2)
.then(foo3)
.then(function(finalData){
return doSomeProcessing(finalData);
})
.catch(function(error){
return $q.reject({msg: "Some error occurred"});
});
}
每个函数的“承诺”返回值是下一个链接函数的输入。
答案 1 :(得分:0)
您可以使用$ q.all方法。例如:
var promises = [promise1, promise2, ...];
$q.all(promises).then(function () {
// do something
});
答案 2 :(得分:0)
现在发生的是所有foo *承诺都取决于单promise
;当它被解决时,所有都被触发。在ASCII艺术中,依赖关系是:
┎ foo1
promise ╁ foo2
┖ foo3
你想要的是:
function doChain() {
foo1()
.then(foo2)
.then(foo3)
;
}
无需额外的promise
。也没有回调地狱!