javascript - 承诺中的 Node.js Promises 不等待 for 循环返回数据
问题描述
return Promise.all([photoArray]) 返回一个空数组,似乎没有等待 callFB 返回它的 promise,然后将其推入数组。
我不确定我做错了什么,但对于带有 for 循环和 Ifs 的 Promises 来说相对较新。
我不确定我是否使用了正确数量的 Promise,但我似乎无法让第三层 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();
})
}
解决方案
该代码受到承诺构造反模式的影响。如果已经有一个 Promise ( Promise.all(...)
),则永远不需要创建一个新的 Promise。
错误的行为是由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 不相互依赖,因此可以安全地同时解决。这允许更快地处理请求。
Promise.all
仅当它用于并行解决 Promise 时才有用,而原始代码试图解决结果(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
口味。
推荐阅读
- google-apps-script - 谷歌应用脚本 | 日历 API - 无效的会议类型值
- ios - 在 iOS 中为 Firebase Analytics 设置用户属性的位置?
- regex - 在 node.js 中匹配特定字母后跟下划线
- python - sys.path.append() 是一个很好的解决方法吗?
- sql-server - 事务日志备份失败并显示“无法获得独占访问权限,因为数据库正在使用中”
- json - 我无法获取 JSON 数据
- javascript - C# Leaflet 如何使用 ajax 正确地将数据从视图发布到控制器?
- javascript - postman.setNextRequest 调用失败
- mysql - 在 MySQL 数据库中搜索查询
- python - Python 模块属性是否在 Python shell 中定义?