Promise中的Node.js承诺不等待循环返回数据

时间:2018-07-31 21:03:15

标签: javascript node.js for-loop promise

返回Promise.all([photoArray])返回一个空数组,似乎不等待callFB返回其诺言,然后将其推入数组。

我不确定自己在做什么错,但对于for循环和Ifs而言,它对于Promises来说相对较新。

我不确定我是否使用了正确数量的Promises,但是我似乎无法获得第三层Promise.all,以等待for循环实际完成(在这种情况下,for循环具有仔细检查许多项目,所以这引起了一个问题,即它不会在调用context.done()之前应触发的所有项目都触发callFeedback。

我也尝试将Q.all也用于Promise.all([photoArray]),但无法正常工作。

module.exports = function (context, myBlob) {
                var res = myBlob
                var promiseResolved = checkPhoto(res,context);
                var promiseResolved2 = checkVideo(res,context); 


            Promise.all([promiseResolved, promiseResolved2]).then(function(results){
            context.log(results[0], results[1]);
 //           context.done();
            });


        });  
    };
};

function checkPhoto(res, context){
    return new Promise((resolve, reject) => {
    if (res.photos.length > 0) {
        var photoArray = [];
        for (var j = 0; j < res.photos.length; j++) {
            if (res.photos[j].feedbackId !== null){
                var feedbackId = res.photos[j].feedbackId;
                var callFB = callFeedback(context, feedbackId);                    
                Promise.all([callFB]).then(function(results){
                    photoArray.push(results[0]);
                 });        
            } else {    
                photoArray.push("Photo " + j + " has no feedback");
            }

        }

        return Promise.all([photoArray]).then(function(results){
            context.log("end results: " + results);
            resolve(photoArray);
        });
    } else {
        resolve('No photos');
    }

})
}
function checkVideo(res, context){
        return new Promise((resolve, reject) => {
            same as checkPhoto
    })
    }
function callFeedback(context, feedbackId) {
        return new Promise((resolve, reject) => {

        var requestUrl = url.parse( URL );

            var requestBody = {
                "id": feedbackId
            };

            // send message to httptrigger to message bot
            var body = JSON.stringify( requestBody );

            const requestOptions = {
            standard
            };

            var request = https.request(requestOptions, function(res) {
                var data ="";
                res.on('data', function (chunk) {
                    data += chunk
    //                context.log('Data: ' + data)
                });
                res.on('end', function () {
                resolve("callFeedback: " + true);
                })
            }).on('error', function(error) {
            });
            request.write(body);
            request.end();
            })

}

1 个答案:

答案 0 :(得分:0)

该代码受promise construction antipattern的影响。如果已经有了一个承诺(Promise.all(...)),则无需创建新的承诺。

错误的行为是由Promise.all(...).then(...)承诺未链接引起的。错误不会得到处理,photoArray.push(results[0])会导致竞争状况,因为它的评估晚于Promise.all([photoArray])...

万一应该并行处理:

function checkPhoto(res, context){
    if (res.photos.length > 0) {
        var photoArray = [];
        for (var j = 0; j < res.photos.length; j++) {
            if (res.photos[j].feedbackId !== null){
                var feedbackId = res.photos[j].feedbackId;
                var callFB = callFeedback(context, feedbackId);
                // likely no need to wait for callFB result
                // and no need for Promise.all
                photoArray.push(callFB);
            } else {    
                photoArray.push("Photo " + j + " has no feedback");
            }
        }

        return Promise.all(photoArray); // not [photoArray]
    } else {
        return 'No photos';
    };
}

callFB的承诺彼此不依赖,因此可以安全地同时解决。这样可以更快地处理请求。

Promise.all仅在用于并行解决承诺时才有用,而原始代码则尝试解决结果(results[0])。

如果应按顺序处理事物,则该功能将从async..await中受益:

async function checkPhoto(res, context){
    if (res.photos.length > 0) {
        var photoArray = [];
        for (var j = 0; j < res.photos.length; j++) {
            if (res.photos[j].feedbackId !== null){
                var feedbackId = res.photos[j].feedbackId;
                const callFBResult = await callFeedback(context, feedbackId);
                // no need for Promise.all
                photoArray.push(callFBResult);
            } else {    
                photoArray.push("Photo " + j + " has no feedback");
            }
        }

        return photoArray; // no need for Promise.all, the array contains results
    } else {
        return 'No photos';
    };
}

添加try..catch来品尝。