如何跳出循环中的一系列异步操作?
How to break out of a sequence of asynchronous operations in a loop?
按照这个例子
Dojo FAQ: How can I sequence asynchronous operations?
function doNext(previousValue) {
var dfd = new Deferred();
// perform some async logic; resolve the promise
setTimeout(function () {
var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1);
dfd.resolve(previousValue + next);
}, 50);
return dfd.promise;
}
var promise = doNext('a');
for (var i = 0; i < 9; i++) {
promise = promise.then(doNext);
}
promise.then(function (finalResult) {
// 'doNext' will have been invoked 10 times, each
// invocation only occurring after the previous one completed
// 'finalResult' will be the value returned
// by the last invocation of 'doNext': 'abcdefghijk'
console.log(finalResult);
});
如何跳出循环——即当 doNext 满足特定条件时停止处理后续的 doNext 函数调用——例如当下一个字符为 'd' 和 return 计算值时停止到那个时候?
编辑: 到目前为止,我尝试使用延迟的 cancel() 方法,但它只是终止了进程,return什么都没有。
setTimeout(function () {
var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1);
if(previousValue + next == 'abc')
dfd.cancel('abc');
else
dfd.resolve(previousValue + next);
}, 50);
您可以通过检查 return 从承诺中编辑的值并决定是否再次调用异步请求来做到这一点。它不像您在 for
循环中添加 break
。但结果会如你所愿。
所有 9 promise.then
都会被调用,但 doNext
不会被调用 9 次。下面是相同的代码段。
for (var i = 0; i < 9; i++) {
promise = promise.then(function(val){
return val === "abcd" ? val : doNext(val);
});
}
您可能认为这不是循环。这是因为循环会在调用回调函数之前完成。但是,回调函数不会调用异步函数,而是简单地 return 该值。这会导致循环快速完成。下面是一个 link 到 JSBin,我在其中增加了超时,您会看到,最初需要更多时间才能获得所需的结果 returned 然后快速退出。
https://jsbin.com/qiwesecufi/edit?js,console,output
另一个可以进行检查的地方是 doNext
函数本身。
function doNext(previousValue) {
var dfd = new Deferred();
if(previousValue === "abcd")
return previousValue;
// perform some async logic; resolve the promise
setTimeout(function () {
var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1);
dfd.resolve(previousValue + next);
}, 1000);
return dfd.promise;
}
希望这对您有所帮助。
当您总是想处理所有项目(或同步决定您需要多少)时,您应该只使用 reduce
(或 promise = promise.then(doNext)
)循环方法。
要循环任意次数并在任何一步中断,递归是更好的方法:
function wait(t, v) {
var dfd = new Deferred();
// asynchronously resolve the promise
setTimeout(function () {
dfd.resolve(v);
}, t);
return dfd.promise;
}
function doNext(previousValue) {
var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1);
return wait(50, previousValue + next);
}
function loop(v, i) {
if (i <= 0) return when(v);
if (v == "abc") return when("abc");
return doNext(v).then(function(r) {
return loop(r, i-1);
});
}
loop('a', 9).then(function (finalResult) {
console.log(finalResult);
});
按照这个例子
Dojo FAQ: How can I sequence asynchronous operations?
function doNext(previousValue) {
var dfd = new Deferred();
// perform some async logic; resolve the promise
setTimeout(function () {
var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1);
dfd.resolve(previousValue + next);
}, 50);
return dfd.promise;
}
var promise = doNext('a');
for (var i = 0; i < 9; i++) {
promise = promise.then(doNext);
}
promise.then(function (finalResult) {
// 'doNext' will have been invoked 10 times, each
// invocation only occurring after the previous one completed
// 'finalResult' will be the value returned
// by the last invocation of 'doNext': 'abcdefghijk'
console.log(finalResult);
});
如何跳出循环——即当 doNext 满足特定条件时停止处理后续的 doNext 函数调用——例如当下一个字符为 'd' 和 return 计算值时停止到那个时候?
编辑: 到目前为止,我尝试使用延迟的 cancel() 方法,但它只是终止了进程,return什么都没有。
setTimeout(function () {
var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1);
if(previousValue + next == 'abc')
dfd.cancel('abc');
else
dfd.resolve(previousValue + next);
}, 50);
您可以通过检查 return 从承诺中编辑的值并决定是否再次调用异步请求来做到这一点。它不像您在 for
循环中添加 break
。但结果会如你所愿。
所有 9 promise.then
都会被调用,但 doNext
不会被调用 9 次。下面是相同的代码段。
for (var i = 0; i < 9; i++) {
promise = promise.then(function(val){
return val === "abcd" ? val : doNext(val);
});
}
您可能认为这不是循环。这是因为循环会在调用回调函数之前完成。但是,回调函数不会调用异步函数,而是简单地 return 该值。这会导致循环快速完成。下面是一个 link 到 JSBin,我在其中增加了超时,您会看到,最初需要更多时间才能获得所需的结果 returned 然后快速退出。
https://jsbin.com/qiwesecufi/edit?js,console,output
另一个可以进行检查的地方是 doNext
函数本身。
function doNext(previousValue) {
var dfd = new Deferred();
if(previousValue === "abcd")
return previousValue;
// perform some async logic; resolve the promise
setTimeout(function () {
var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1);
dfd.resolve(previousValue + next);
}, 1000);
return dfd.promise;
}
希望这对您有所帮助。
当您总是想处理所有项目(或同步决定您需要多少)时,您应该只使用 reduce
(或 promise = promise.then(doNext)
)循环方法。
要循环任意次数并在任何一步中断,递归是更好的方法:
function wait(t, v) {
var dfd = new Deferred();
// asynchronously resolve the promise
setTimeout(function () {
dfd.resolve(v);
}, t);
return dfd.promise;
}
function doNext(previousValue) {
var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1);
return wait(50, previousValue + next);
}
function loop(v, i) {
if (i <= 0) return when(v);
if (v == "abc") return when("abc");
return doNext(v).then(function(r) {
return loop(r, i-1);
});
}
loop('a', 9).then(function (finalResult) {
console.log(finalResult);
});