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!");
    }
)