promise.all里异步比for of循环做异步操作时间更快吗?
发布于 5 年前 作者 liufeisprit 6405 次浏览 来自 问答

按理说promise.all里异步是并行的 for of循环做异步操作是串行的 在promise.all方法里运行时间应该更短,但是遇到了问题? 为什么在promise.all()方法中做mongoDB的查询操作 要比在for of里的做同样的操作时间更久 promise.all方法 如图 1559812126(1).jpg 运行时间 image.png

for of方法 如图 image.png 运行时间 image.png

刚学node不久 求大佬解答

	async function test(){
	  let userItem=await User.find({},{uid:1,_id:0}).limit(10)
	  console.time('程序耗时')
	  // for(var item of userItem){
	  //     await User.findOne({
	  //         uid:item.uid
	  //     })
	  // }
	  await Promise.all(userItem.map(async item=>{
		  let user=await User.findOne({
			  uid:item.uid
		  })
		  return user
	  }))
    console.timeEnd('程序耗时')
}
24 回复

第一个试试这样: ··· … … userItem.map( return User.findOne(…) // 去掉 await ···

ps: 你不贴源码,别人你修改很不方便。

@waitingsong 好的 ! 谢谢 我贴上啦

试试这个:

 await Promise.all(userItem.map(item=>{
		  return User.findOne({
			  uid:item.uid
		  })
		  
	  }))

@waitingsong 我试了一下 好像没多大变化 跟之前的时间差不多长

那你在最里层迭代里打个时间戳日志看看

是不是数据库连接不稳啊,除了map里面多余了await,感觉没什么不对的,但就算多了await,影响应该也不大啊,诡异。。。

可能是数据库连接或者缓存的问题吧,你试下这样子

async function test(){
	  let userItem=await User.find({},{uid:1,_id:0}).limit(10)
	  console.time('程序耗时1')
	   for(var item of userItem){
	       await User.findOne({
	           uid:item.uid
	       })
	  }
	  console.timeEnd('程序耗时1')
	  console.time('程序耗时2')
	  await Promise.all(userItem.map(async item=>{
		  let user=await User.findOne({
			  uid:item.uid
		  })
		  return user
	  }))
    console.timeEnd('程序耗时2')
}

你看下这个输出。 或者不要查数据库,使用sleep暂停看下

function sleep(time) {
  return new Promise(resolve => {
    setTimeout(() => {
      return resolve();
    }, time);
  });
}

async function test() {
  const userItem = await User.find({}, '_id').limit(10);
  console.time('程序耗时1');
  for (const item of userItem) {
    await sleep(1000);
  }
  console.timeEnd('程序耗时1');
  console.time('程序耗时2');
  await Promise.all(userItem.map(async item => {
    const user = await sleep(1000);
    return user;
  }));
  console.timeEnd('程序耗时2');
}

@jiangli373 我发现如果是在里面做fetch请求 promise.all就很快 做数据库操作就很慢

@jiangli373 我试了下sleep发现是正常的

 	 forof程序耗时: 10002.123ms  
  	 promiseAll程序耗时: 1000.107ms

但是一查数据库就不一样了 promise.all查询完感觉总是卡住一阵子才结束 不知道为什么?

@DuJiming 我也觉得 但是为什么for of就是好的 promise.all方法查完数据后会卡住好久 才返回 好奇怪啊啊啊啊

估计是lz的mongo那儿有问题吧。

原生的 async/await 记得国外有篇文章分析在Promise.all参数数组比较大的情况下,不如用第三方的库比如bluebird

@waitingsong 我也觉得诶,我这个mongo是连的本地的 🌚你有遇到过这样的问题嘛

贴下连接mongodb的代码看看呢

@lzszone 这个for in中的t是计数吧,不是遍历timeouts吧,你输出下t试试呢

@DuJiming …删了…丢人…退坛:( 不知道答案…

@lzszone 别别,当我没说。。。

mongodb 连接池调大点。

@jiangli373

	const mongoose = require('mongoose')
	exports.connect = (DB_URL) => {
    return new Promise((resolve, reject) => {
        let maxConnectTimes=0
        if (process.env.NODE_ENV !== 'production') {
            mongoose.set('debug', true)
        }
        mongoose.connect(DB_URL)
        mongoose.connection.on('disconnected', (err) => {
            console.log('disconnected',err)
            if(maxConnectTimes<5){
                mongoose.connect(DB_URL)
            }else{
                throw new Error('数据库挂了')
            }
        });
        mongoose.connection.on('error', err => {
            console.log('error',err)
            maxConnectTimes++
            if(maxConnectTimes<5){
                mongoose.connect(DB_URL)
            }else{
                throw new Error('数据库挂了')
            }
        });
        mongoose.connection.once('open', data => {
            console.log('mongodb connected success')
            resolve()
        });
    })
}

@htoooth 我就十条测试数据还要设置这个吗 默认就是五个连接池吧? 你有遇到过这样的嘛?

promise.all意思应该是将[]Promise一并全部执行,你这里把具体的user给return了,all()里面不是[]promise,这样我不确定有没有问题,另外,正常的用法来说promise.all()是并行的,而你的for里面await是串行的,就是一个是一下子全放入队列等待resolve,另一个是运行完一个才运行下一个。我认为你那个map也是可以的,并且也是并行的,一下子就把所有操作放入队列,而这样,有可能就是你的mongo数据库方面的问题,导致时间长。而for的方法是串行的,某种原因导致这样做会更快,反正两种方式是不同的。

@liufeisprit 试试查询的时候改成5条看看呢,尝试不同的查询条数,看下时间对比

@jiangli373 五条也是 时间是比十条快 但是还是比for循环慢了很多 主要是感觉数据都查完了 但是会卡住很久才返回

回到顶部