在 forEach 循环完成后运行回调函数

Posted

技术标签:

【中文标题】在 forEach 循环完成后运行回调函数【英文标题】:run a callback function after forEach loop finish 【发布时间】:2019-03-25 17:41:16 【问题描述】:

如何在 forEach 循环结束后回调 timer() 函数,使用相同的代码。还是有更好的方法来延迟循环遍历每个用户,然后在循环完成后,使用 forEach 回调 timer()。

  const usersProfile = () => 
  let interval = 1000;
  let promise = Promise.resolve();
  db.select('*').from('users')
    .returning('*')
    .then(users => 
      users.forEach((user, index) => 
        setTimeout(function()

        , index * 1000)
        db.select('*').from(`$user.name`)
          .returning('*')
          .then(userdata => 
            userdata.forEach(data => 
                promise = promise.then(function()
                  if(data.status === 'online')
                    console.log(`$data.name $data.items $data.profile $data.images`)
                  
                return new Promise(function(resolve)
                    setTimeout(function()
                      resolve();
                    , interval)
                )
              )
            )
          )
      )
       timer();
    )

const timer = () => 
  setTimeout(usersProfile, 1000)

timer();

===============以上都是我的旧代码================ 但感谢https://***.com/users/2404452/tho-vu 它解决了大部分问题,但我可以这样做以服务于应用程序的目的吗

const usersProfile = async () => 
  let interval = 1000;

  const delayPromise = (data, delayDuration) => 
    return new Promise((resolve) => 
      setTimeout(() => 
        if(data.status === 'online')
          console.log(`$data.name $data.items $data.profile $data.images`);
          resolve();
        
      , delayDuration)
    );
  ;

 const userInfo = (data, delayDuration) => 
    return new Promise((resolve) => 
      setTimeout(() => 
          console.log(`$data.info`);//info about user from his table each user has his own table besides users table that has only the user tables
          resolve();
      , delayDuration)
    );
  ;
  try 
    const userData = await db.select('*').from('users').returning('*');
    const promises = userData.map((data, index) => delayPromise(data, index * interval));
    const userData = await db.select('*').from(`$data.name`).returning('*');
    const info = userData.map((data, index) => userInfo(data, index * interval));
    await Promise.all(promises);
    // here you can write your effects
   catch (e) 
    console.log(e);
  

【问题讨论】:

你试过if index = last then use timer() 见***.com/a/31414472/1348195 @BenjaminGruenbaum 你能给我一个例子来处理我的案例吗?我将不胜感激,我已经阅读了它,但仍然不知道如何在我的代码中使用它 @BladeMight 是的,但没用。 【参考方案1】:

我很难完全理解你想通过代码完成什么,但我会尝试解释你可以做些什么来解决这个问题。

首先,如果你想等待多个promise,你应该使用Promise.all而不是promise = promise.then

你可以这样做:

let promises = [];
users.forEach((user, index) => 
   let promise = db.select(*).from('users') //should return a promise
   promises.push(promise);
);

//promises have already started to execute (in parallel)

Promise.all(promises)
.then(() => console.log('all promises finished successfully'))
.catch((e) => console.error('received error at one of the promises'));


 // when the program arrives here we know for a fact that either all promises executed successfully or one of the promises failed

timer();

说明:因为 promise 是异步执行的,所以 forEach() 函数不会等待任何创建的 promise 完成,所以解决方案是在整个循环之后等待所有 promise。

这意味着 Promise 被创建,并在 forEach() 循环并行执行时被执行,当程序到达 Promise.all 时,它会停止并等待它们全部完成。

其次,我强烈建议您使用函数来简化代码,这样您就可以更轻松地掌握正在发生的每一件事,即使它很复杂。

祝你好运!

【讨论】:

我已经编写了这段代码,用于在每个项目之间将 forEach 循环中的迭代延迟 1000 毫秒。 我已经更新了代码来解释我期望从这段代码中发挥什么作用【参考方案2】:

另一种使用async-await 来避免回调地狱的方法。

const usersProfile = async () => 
  let interval = 1000;

  const delayPromise = (data, delayDuration) => 
    return new Promise((resolve) => 
      setTimeout(() => 
        if(data.status === 'online')
          console.log(`$data.name $data.items $data.profile $data.images`);
          resolve();
        
      , delayDuration)
    );
  ;

  try 
    const userData = await db.select('*').from('users').returning('*');
    const promises = userData.map((data, index) => delayPromise(data, index * interval));
    await Promise.all(promises);
    // here you can write your effects
   catch (e) 
    console.log(e);
  

【讨论】:

const userData = await db.select('').from('users').returning('');我可以像这样调用这段代码中的数据吗 const userData = await db.select('').from($data.name).returning('');所以我可以运行第二个循环来获取我为每个用户创建的每个表中的信息 @The4thpyramid 可以,但delayPromise 可能需要更改以适应修改。就个人而言,我建议您寻找更好的数据库查询,例如一个连接查询,用于在一个 db.select 中获取所有用户个人数据,而不是像您想要的那样链接查询。

以上是关于在 forEach 循环完成后运行回调函数的主要内容,如果未能解决你的问题,请参考以下文章

等待函数完成,直到回调到来

arguments,foreach循环,重载,回调函数,对象继承

knockout.js 完成渲染所有元素后的成功回调

使用 forEach 时避免回调多次调用

promise核心技术 2.两种回调函数 js中error的处理

for循环,foreach, map,reduce用法对比+for in,for of