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

按理说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循环慢了很多 主要是感觉数据都查完了 但是会卡住很久才返回

回到顶部