按理说promise.all里异步是并行的 for of循环做异步操作是串行的 在promise.all方法里运行时间应该更短,但是遇到了问题? 为什么在promise.all()方法中做mongoDB的查询操作 要比在for of里的做同样的操作时间更久 promise.all方法 如图 运行时间
for of方法 如图 运行时间
刚学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('程序耗时')
}
第一个试试这样: ··· … … 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是连的本地的 🌚你有遇到过这样的问题嘛
@liufeisprit 没用过 mongo
贴下连接mongodb的代码看看呢
@lzszone 这个for in
中的t
是计数吧,不是遍历timeouts
吧,你输出下t
试试呢
@DuJiming …删了…丢人…退坛:( 不知道答案…
@lzszone 别别,当我没说。。。
mongodb 连接池调大点。
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循环慢了很多 主要是感觉数据都查完了 但是会卡住很久才返回