遇到了在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 }
}
打开下面的网页自己试一下。
http://www.typescriptlang.org/play/index.html#src= let arr %3D [] for (let i %3D 0%3B i < 2%3B i%2B%2B){ const ret %3D ((async (i) %3D> { return Promise.resolve(i) })(i))%3B%0D%0A%20%20%20%20arr.push(ret)%0D%0A%7D%0D%0A%0D%0Aconsole.log(arr)%0D%0A%0D%0A
没问题的,自己 catch 一下。
let testDataList = await Promise.all(dataList);
async 函数返回的就是一个 Promise,你的 datalist push 进去的当然也是个 pending 状态的 Promise,所以里面的 await 调试取值的时候也是一个 pending 状态的 Promise,当然也就看起来跳过了
先不说别的,你上面代码中是不是漏了什么,doc 没有声明啊,或者忘执行函数了
@rrbe 我想得到的是resolve之后的值,有什么办法能够让它完成后再执行呢
@ZCZ12138 当然参考是 2 楼朴灵大大的回复~ 哈哈 当然你要把外层也用 async 函数包起来
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)
})()
@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)
@JacksonTian 您的建议确实让人耳目一新,但我测试后发现all之后的值少了一个字段,不太确定是不是这样写的原因,我改用async.eachSeries是可以获取到完整的数据的,而且请求在Chrome里面没有response data,这是为什么?
async (xxx) => { const query = await model.xx.find(); if(query && query.length) { for(let i in query){ let data = await model.xxx.find(i) } } }
我平时就是这样用的,不知道是否符合你的要求
Promise.all(findOne(), findOne())
.then(results=>{ // results })
ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
有始有终一下,Promise.all确实有效,少字段是因为assign函数的问题,没有response data是因为浏览器,感谢大家的建议。另外有关于遍历中的异步操作,大家有什么更好的建议请不要吝啬,随意砸到我脸上 》_《
我觉得大家没有引导楼主到正确的姿势上额,楼主对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))
@fantasticsoul await就是在async函数的promise变为resolved后,相当于.then((value) => {}),而不加await关键字只是个待完成的promise而已,而我题目中明明已经await了,但还是不能等到了resolved后才执行下文,这让我很困惑,或许还是陷入怪圈出不来了 (ノへ ̄、)
@qiu363 因为 async 返回的是一个 promise
@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)
}
你试一下push()里面的匿名函数执行完后给个.then(result => result) ,这样push((async fun)(i).then(result => result)), 不知道行不行,如果可以 那么 在前面 加个push( await (async funtion(){})(i)) 应该也可以
试了一下 发现 加.then()那个不可以的,await匿名函数前面加个 await是可以的,第一个不行的原因不太清楚,报的错是[ Promise { [Circular] }, Promise { [Circular] } ],