Javascript 如何回报许多承诺,并在做其他事情之前等待所有承诺
我有一个循环,它调用一个异步执行内容的方法。这个循环可以多次调用该方法。在这个循环之后,我有另一个循环,它只需要在所有异步工作完成时执行 这说明了我想要什么:Javascript 如何回报许多承诺,并在做其他事情之前等待所有承诺,javascript,asynchronous,ecmascript-6,promise,es6-promise,Javascript,Asynchronous,Ecmascript 6,Promise,Es6 Promise,我有一个循环,它调用一个异步执行内容的方法。这个循环可以多次调用该方法。在这个循环之后,我有另一个循环,它只需要在所有异步工作完成时执行 这说明了我想要什么: for (i = 0; i < 5; i++) { doSomeAsyncStuff(); } for (i = 0; i < 5; i++) { doSomeStuffOnlyWhenTheAsyncStuffIsFinish(); } 也许我必须这样做: function doSomeA
for (i = 0; i < 5; i++) {
doSomeAsyncStuff();
}
for (i = 0; i < 5; i++) {
doSomeStuffOnlyWhenTheAsyncStuffIsFinish();
}
也许我必须这样做:
function doSomeAsyncStuff() {
var editor = generateCKEditor();
return new Promise(function(resolve,refuse) {
editor.on('instanceReady', function(evt) {
doSomeStuff();
resolve(true);
});
});
}
但是我不确定语法。你可以使用
承诺。所有(,)承诺:它接受一系列单独的承诺,并返回一个单独的承诺,当你给出的所有承诺都得到解决时,该承诺会得到解决;当任何承诺被拒绝时,该承诺会被拒绝
因此,如果您做出doSomeAsyncStuff
返回承诺,那么:
const promises = [];
// ^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−− use `const` or `let`, not `var`
for (let i = 0; i < 5; i++) {
// ^^^−−−−−−−−−−−−−−−−−−−−−−−− added missing declaration
promises.push(doSomeAsyncStuff());
}
Promise.all(promises)
.then(() => {
for (let i = 0; i < 5; i++) {
// ^^^−−−−−−−−−−−−−−−− added missing declaration
doSomeStuffOnlyWhenTheAsyncStuffIsFinish();
}
})
.catch((e) => {
// handle errors here
});
const promises=[];
// ^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−− 使用'const'或'let',而不是'var'`
for(设i=0;i<5;i++){
// ^^^−−−−−−−−−−−−−−−−−−−−−−−− 添加了缺少的声明
promises.push(doSomeAsyncStuff());
}
所有(承诺)
.然后(()=>{
for(设i=0;i<5;i++){
// ^^^−−−−−−−−−−−−−−−− 添加了缺少的声明
DoSomeStuff仅在SyncStuff为Finish()时使用;
}
})
.catch((e)=>{
//在这里处理错误
});
MDN有一篇关于承诺的文章。我还将在我的《JavaScript:新玩具》一书的第8章中详细介绍承诺,如果您感兴趣,请参阅我个人资料中的链接
下面是一个例子:
函数doSomethingAsync(值){
返回新承诺((解决)=>{
设置超时(()=>{
console.log(“解析”+值);
决心(价值);
},Math.floor(Math.random()*1000));
});
}
功能测试(){
常量承诺=[];
for(设i=0;i<5;++i){
promises.push(doSomethingAsync(i));
}
所有(承诺)
。然后((结果)=>{
console.log(“全部完成”,结果);
})
.catch((e)=>{
//在这里处理错误
});
}
test()代码>可重用函数很好地适用于此模式:
function awaitAll(count, asyncFn) {
const promises = [];
for (i = 0; i < count; ++i) {
promises.push(asyncFn());
}
return Promise.all(promises);
}
一个相关的模式是迭代数组并对每个项执行异步操作:
function awaitAll(list, asyncFn) {
const promises = [];
list.forEach(x => {
promises.push(asyncFn(x));
});
return Promise.all(promises);
}
例如:
const books = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }];
function doSomeAsyncStuffWith(book) {
return Promise.resolve(book.name);
}
awaitAll(books, doSomeAsyncStuffWith)
.then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
.catch(e => console.error(e));
以下是我为自己编写的代码,以便理解此处所述的答案。我在for循环中有mongoose查询,所以我在这里放置了asyncFunction
来代替它。希望它能帮助任何人。您可以在node或许多Javascript运行时中的任何一个运行此脚本
let asyncFunction = function(value, callback)
{
setTimeout(function(){console.log(value); callback();}, 1000);
}
// a sample function run without promises
asyncFunction(10,
function()
{
console.log("I'm back 10");
}
);
//here we use promises
let promisesArray = [];
let p = new Promise(function(resolve)
{
asyncFunction(20,
function()
{
console.log("I'm back 20");
resolve(20);
}
);
});
promisesArray.push(p);
for(let i = 30; i < 80; i += 10)
{
let p = new Promise(function(resolve)
{
asyncFunction(i,
function()
{
console.log("I'm back " + i);
resolve(i);
}
);
});
promisesArray.push(p);
}
// We use Promise.all to execute code after all promises are done.
Promise.all(promisesArray).then(
function()
{
console.log("all promises resolved!");
}
)
let asyncFunction=function(值,回调)
{
setTimeout(函数(){console.log(value);回调();},1000);
}
//示例函数在没有承诺的情况下运行
异步函数(10,
函数()
{
log(“我回来了10”);
}
);
//这里我们使用承诺
让允诺人雷=[];
设p=新承诺(函数(解析)
{
异步函数(20,
函数()
{
log(“我回来了20”);
决议(20);
}
);
});
promisesArray.push(p);
对于(设i=30;i<80;i+=10)
{
设p=新承诺(函数(解析)
{
异步函数(i,
函数()
{
log(“我回来了”+I);
决议(i);
}
);
});
promisesArray.push(p);
}
//我们使用Promise.all在所有承诺完成后执行代码。
保证,一切(承诺),然后(
函数()
{
log(“所有承诺已解决!”);
}
)
/***最糟糕的方式***/
对于(i=0;i),由于所有api调用
//将连续发生
/***最好的方法之一***/
const yourAsyncFunction=async(anyParams)=>{
让数据=等待axios.get(
"https://yourwebsite.com/get_my_data/"
)
//所有的语句和操作都在这里
//依赖于数据的
}
var承诺=[]
对于(i=0;i),此方法的执行速度与所有api调用一样快
//将在视差中发生
您是否控制异步调用?它们是否已经返回承诺,或者您是否可以让它们返回承诺?具体顺序是什么?您是否需要在所有先前的异步调用完成后调用其他函数?还是只需要在每个异步调用完成后调用一个函数?否w第一个函数不返回承诺。我必须实现这些承诺。我想编辑我的消息,以添加我函数工作流的一些细节。是的,我需要在开始执行第二个循环之前完成第一个循环的所有内容。重新编辑:“也许我必须这样做”是的,非常像那样,除了在承诺
的结尾没有s
。哇,非常感谢,现在我了解了更多的承诺。我读了很多关于承诺的书,但直到我们需要在真正的代码中使用它们,我们才真正了解所有的机制。现在我做得更好了,我可以开始写很酷的东西了,谢谢你。还有,如果出于任何原因(例如模拟进度)希望按顺序完成这些任务,可以将Math.floor(Math.random()*1000)
更改为(i*1000)
@user1063287-如果代码处于允许使用await
的上下文中,则可以执行此操作。目前,唯一可以使用await
的地方是async
函数内部。(在某个时候,您还可以在模块的顶层使用它。)谢谢,为我工作!谢谢@Henke!我已经修复了链接。这真的使代码更容易理解和更干净。我认为当前的示例(显然是根据OP的代码改编的)不能做到这一点。这是一个巧妙的技巧,谢谢!
const books = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }];
function doSomeAsyncStuffWith(book) {
return Promise.resolve(book.name);
}
awaitAll(books, doSomeAsyncStuffWith)
.then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
.catch(e => console.error(e));
const doSomeAsyncStuff = async (funcs) => {
const allPromises = funcs.map(func => func());
return await Promise.all(allPromises);
}
doSomeAsyncStuff([
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
]);
let asyncFunction = function(value, callback)
{
setTimeout(function(){console.log(value); callback();}, 1000);
}
// a sample function run without promises
asyncFunction(10,
function()
{
console.log("I'm back 10");
}
);
//here we use promises
let promisesArray = [];
let p = new Promise(function(resolve)
{
asyncFunction(20,
function()
{
console.log("I'm back 20");
resolve(20);
}
);
});
promisesArray.push(p);
for(let i = 30; i < 80; i += 10)
{
let p = new Promise(function(resolve)
{
asyncFunction(i,
function()
{
console.log("I'm back " + i);
resolve(i);
}
);
});
promisesArray.push(p);
}
// We use Promise.all to execute code after all promises are done.
Promise.all(promisesArray).then(
function()
{
console.log("all promises resolved!");
}
)