假设您有一个包含值列表的数组/对象。比方说那些 mysql 命令或 url 或文件路径。现在您想要迭代所有这些并对每个条目执行一些代码。
for(let i = 0; i < urls.length; i++){
doSthWith(urls[i]);
}
到目前为止没有问题。但现在假设每个函数都有一个回调并且需要上次执行的结果。例如您向一个网站请求某项内容,并且希望将此请求的结果用于您的以下请求之一。
for(let i = 0; i < urls.length; i++){
if(resultOfLastIteration.successful){ //or some other result besides the last one
doSthWith(urls[i]);
}
}
现在假设 url(或类似的东西)的长度超过 100。这就是为什么你通常使用循环,这样你就不需要编写相同的函数 100 次。这也意味着 Promise 也不会成功(除了我不知道的技巧),因为你有同样的问题:
doSthWith(urls[0]).then(...
doSthWith(urls[1]).then(... //either put them inside each other
).then(...
doSthWith(urls[i]) //or in sequence
...
).catch(err){...}
无论哪种方式,我都看不到使用循环的方法。
我发现但并不是真正“好”的一种方法是使用包“wait.for”( https://www.npmjs.com/package/wait.for )。但是这个包的棘手之处在于每次你想使用 wait.for 时都要启动一个 Fiber:
//somewhere you use the function in a fiber Context
wait.for(loopedExecutionOfUrls, urls);
//function declaration
function loopedExecutionOfUrls(urls, cb){
//variables:
for(let i = 0; i < urls.length; i++){
if(someTempResultVar[i-1] === true){
someTempResultVar = wait.for(doSthWith,urls[i]);
} else if(...){...}
}
}
但我不确定这种方法是否真的很好,此外,您总是必须检查是否已将整个内容包装在 Fiber 中,因此对于每个具有带有回调函数的循环的函数。因此,您有 3 个级别:lauchFiber 级别、wait.for(loopedFunction) 级别和 wait.for 回调函数级别。 (希望我的表述是可以理解的)
所以我的问题是:你们有没有一个好的方法可以循环抛出回调函数并且可以随时使用这些函数的结果?
好=易于使用、阅读、高性能、非递归...
(如果这个问题很愚蠢,我很抱歉,但我在异步编程方面确实遇到了问题)
最佳答案
如果您想等待 doSthWith
完成,然后再执行相同的操作,但使用下一个 url,则必须链接您的 Promise,并且可以使用 array.prototype.reduce
这样做:
urls = ["aaa", "bbb", "ccc", "ddd"];
urls.reduce((lastPromise, url) => lastPromise.then((resultOfPreviousPromise) => {
console.log("Result of previous request: ", resultOfPreviousPromise); // <-- Result of the previous request that you can use for the next request
return doSthWith(url);
}), Promise.resolve());
function doSthWith(arg) { // Simulate the doSthWith promise
console.log("do something with: ", arg);
return new Promise(resolve => {
setTimeout(() => resolve("result of " + arg), 2000);
});
}
关于javascript - 循环和回调 hell ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48302502/