CNode

async/await与for循环遍历

问答
ZZCZ12138发布于8 年前最后回复8 年前20 回复11594 浏览0 收藏

遇到了在for循环中,使用await函数的情况,但是打断点调试后发现得到的还是Promise{pending},有考虑闭包的问题,使用了匿名函数带参数的写法,还是不能解决,每次单步调试的时候await函数那里会自动跳过,代码如下,请熟悉这方面的朋友给点意见,指明一个研究方向,谢谢。

var query = models.DuoBaoPlayer.find(q, '').sort('-_id').skip(skipFrom).limit(limit);

query.exec(function(err, doc) {
    var dataList = [];
    
	async function findOneDuobao(item) {
        let doc = await models.DuoBao.findOne({id:item.sid}, 'title startTime endTime luckys totalTime haveTime winner');		//mongoose
        return doc;
    }
        
    for (let i = 0; i < doc.length; i++) {
        dataList.push((async function (num) {
            let data1 = doc[num].toObject();			
            let data2 = await findOneDuobao(doc[num]);              //每次单步调试的时候都会自动跳过
            let data = Object.assign(data1, data2);
            return data;
        })(i));
    }
    
    let testDataList = dataList;                //return 两个 Promise { pending }
}
查看回复

回复 (20)

R
rrbe#2·8 年前
引用 ZCZ12138@rrbe 我想得到的是resolve之后的值,有什么办法能够让它完成后再执行呢

@ZCZ12138 当然参考是 2 楼朴灵大大的回复~ 哈哈 当然你要把外层也用 async 函数包起来

Y
yangzichen987046#3·8 年前
  let dataList = [];

  function findOneDuobao(item) {
    return new Promise((resolve) => {
      setTimeout(function () {
        resolve(item)
      },Math.random()*1000);
    });
  }

  (async function() {
    for (let i=0;i<10;i++) {
      let result=await findOneDuobao(i)
      console.log(result)
      dataList.push(result)
    }
    console.log(dataList)
  })()
M
Michaelooo#5·8 年前
引用 ZCZ12138@Michaelooo function(err, doc) { }

@ZCZ12138 眼瞎没看到……其他的感觉没毛病啊,我测的OK啊

async function findone() {
    return { 'aa': '11'};
}

async function findOneDuobao (a) {
    let ret = await findone();
    return ret;
}

var dataList = [];
for (let i = 0; i < 2; i++) {
  dataList.push((async function (num) {
    let data1 = {'data' : '22'};
    let data2 = await findOneDuobao({ 'data' : '33'});              //每次单步调试的时候都会自动跳过
    let data = Object.assign(data1, data2);
    return data;
  })(i));
}

console.log(dataList)
Z
ZCZ12138#6·8 年前
引用 JacksonTian

@JacksonTian 您的建议确实让人耳目一新,但我测试后发现all之后的值少了一个字段,不太确定是不是这样写的原因,我改用async.eachSeries是可以获取到完整的数据的,而且请求在Chrome里面没有response data,这是为什么?

E
enternoder#7·8 年前

async (xxx) => { const query = await model.xx.find(); if(query && query.length) { for(let i in query){ let data = await model.xxx.find(i) } } }

我平时就是这样用的,不知道是否符合你的要求

Z
ZCZ12138#8·8 年前

有始有终一下,Promise.all确实有效,少字段是因为assign函数的问题,没有response data是因为浏览器,感谢大家的建议。另外有关于遍历中的异步操作,大家有什么更好的建议请不要吝啬,随意砸到我脸上 》_《

H
heguangda#9·8 年前

你试一下push()里面的匿名函数执行完后给个.then(result => result) ,这样push((async fun)(i).then(result => result)), 不知道行不行,如果可以 那么 在前面 加个push( await (async funtion(){})(i)) 应该也可以

H
heguangda#10·8 年前

试了一下 发现 加.then()那个不可以的,await匿名函数前面加个 await是可以的,第一个不行的原因不太清楚,报的错是[ Promise { [Circular] }, Promise { [Circular] } ],

J
JacksonTian#12·8 年前
let testDataList = await Promise.all(dataList);
R
rrbe#13·8 年前

async 函数返回的就是一个 Promise,你的 datalist push 进去的当然也是个 pending 状态的 Promise,所以里面的 await 调试取值的时候也是一个 pending 状态的 Promise,当然也就看起来跳过了

M
Michaelooo#14·8 年前

先不说别的,你上面代码中是不是漏了什么,doc 没有声明啊,或者忘执行函数了

S
Soontao#15·8 年前
Promise.all(findOne(), findOne())
	.then(results=>{ // results })

ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

F
fantasticsoul#16·8 年前

我觉得大家没有引导楼主到正确的姿势上额,楼主对async 和 await 还缺一点点更深刻的理解,这里给你个引导吧:

const exec = models.DuoBaoPlayer.find(q, '').sort('-_id').skip(skipFrom).limit(limit).exec;

async function findOneDuobao(item) {
        let doc = await models.DuoBao.findOne({id:item.sid}, 'title startTime endTime luckys totalTime haveTime winner');		//mongoose
        return doc;
}

exec(function(err, doc) {
    (async (err,  doc)=>{
	  var dataList = [];
	   
	   //写法1,一个一个执行
	  for (let i = 0; i < doc.length; i++) {
	       let data1 = doc[i].toObject();	
           dataList.push(await findOneDuobao(doc[i]));   		   
	  }		
	  
	  //写法2,用Promise.all
	 const tasks = [];
	 for (let i = 0; i < doc.length; i++) {
	       tasks.push(findOneDuobao(doc[i]));
	  }	
	  dataList = Promise.all(tasks);
	  
	}))(err, doc)
}

//或者在封装一下写法如下:
const wrapFn = asyncFn => (err, doc) => asyncFn(err, doc); 
async function findDataList(err,  doc){
	  var dataList = [];
	  for (let i = 0; i < doc.length; i++) {//这里如上,写法1和写法2都ok
	       let data1 = doc[i].toObject();	
           dataList.push(await findOneDuobao(doc[i]));   		   
	  }	
	  return dataList;	  
}
exec(wrapFn(findDataList));

//或者再简单粗暴点
const util = require('util');
const exec = models.DuoBaoPlayer.find(q, '').sort('-_id').skip(skipFrom).limit(limit).exec
const execPromise = util.promisify(exec);

const findDataList = async function(){
	const docs = await execPromise();
	const dataList = [];
	const len = docs.length;
    for (let i = 0; i < len; i++) {
           dataList.push(await findOneDuobao(docs[i]));   		   
	}
	return dataList
}

findDataList().then(dataList=> console.log(dataList)).catch(err=> console.log(err))

Z
ZCZ12138#17·8 年前
引用 fantasticsoul我觉得大家没有引导楼主到正确的姿势上额,楼主对async 和 await 还缺一点点更深刻的理解,这里给你个引导吧:

@fantasticsoul await就是在async函数的promise变为resolved后,相当于.then((value) => {}),而不加await关键字只是个待完成的promise而已,而我题目中明明已经await了,但还是不能等到了resolved后才执行下文,这让我很困惑,或许还是陷入怪圈出不来了 (ノへ ̄、)

A
atian25#19·8 年前
引用 qiu363@ZCZ12138

@qiu363 因为 async 返回的是一个 promise

F
fantasticsoul#20·8 年前
引用 ZCZ12138@fantasticsoul await就是在async函数的promise变为resolved后,相当于.then((value) = {}),而不加await关键字只是个待完成的promi...

@ZCZ12138 谷歌浏览器console里执行如下代码,没问题啊

for(var i=1;i<5;i++){
	(async(i)=>{
        console.log(i);
        var resp = await fetch('http://www.zzkai.com:8888/getbooks');
        var json = await resp.json();
        console.log(i,json);
	})(i)
}
参与回复
登录后即可参与回复。登录