我问了有关如何循环运行异步方法的问题。我现在正在以类似递归的方式进行操作。
How can asynchronous method in loop executed in sequence?
但是,如果第二次成功获取数据库数据,现在我无法将数据传递给最终回调(代码的最后一行)。
function CallGetDB(UID) {
return new Promise(function(resolve, reject){
GetDynamodb(UID)
.then((data)=> {
console.log("check before if"+JSON.stringify(data));
dbResponse = data;
resolve(dbResponse);
}
)
.catch((data)=> {
if(index++ < 2)
{
console.log("This is "+(index+1)+" try to get data from db with UID.");
setTimeout(function(){CallGetDB(UID);},100);
}
else
{
console.log("Database multi fetch failed");
resolve("Database multi fetch failed");
}
});
});
SendSQS(UID,event).then((data)=>{
return CallGetDB(data);
}).then((data)=>{
console.log("I am at most out:" +JSON.stringify(data));
response.body=JSON.stringify(data);
callback(null,response);
});
答案 0 :(得分:1)
将GetDynamodb(UID)
包装在new Promise
中是一种反模式,因为它会返回一个承诺。
以下操作会添加一个retries
参数,默认值为CallGetDB()
,并且当重试在限制范围内时,会在catch()
中返回一个新的诺言...。或者抛出新的错误以获取陷入了以下catch()
let sleep = ms => new Promise(r => setTimeout(r, ms));
function CallGetDB(UID, retries = 0) {
return GetDynamodb(UID)
.catch((data) => {
if (retries++ < 2) {
console.log("This is " + (retries + 1) + " try to get data from db with UID.");
// return another promise
return sleep(100).then(() => CallGetDB(UID, retries));
} else {
console.log("Database multi fetch failed");
// throw error to next catch()
throw new Error("Database multi fetch failed");
}
});
}
SendSQS(UID, event).then((data) => {
return CallGetDB(data);
}).then((data) => {
console.log("Data Success:" + JSON.stringify(data));
response.body = JSON.stringify(data);
callback(null, data);
}).catch(err => /* do something when it all fails*/ );
答案 1 :(得分:1)
发生错误并且index
小于2时,您的承诺无法兑现。
if(index++ < 2){
console.log("This is "+(index+1)+" try to get data from db with UID.");
setTimeout(function(){CallGetDB(UID);},100);
}
到那时,您的承诺将永远不会实现或拒绝,因为原始的承诺永远不会得到实现,并且无法resolve
JSON数据也不会到达您的else
分支。这变成了一个未解决的承诺(一个承诺无限期地拖延)。不过,如果GetDynamodb
第一次尝试完成,它将起作用。
您可以通过履行if
分支内的承诺来解决此问题:
setTimeout(function(){resolve(CallGetDB(UID));},100);
话虽这么说,您可能不应该包装这样的承诺。这与您的方法有点相似:
let delay = ms => new Promise(r => setTimeout(r, ms));
function CallGetDB(UID) {
return GetDynamodb(UID).then(data => {
console.log("check before if"+JSON.stringify(data));
return data;
}).catch(err => {
if(index++ < 2){
console.log("This is "+(index+1)+" try to get data from db with UID.");
return delay(100).then(() => CallGetDB(UID));
} else {
console.log("Database multi fetch failed");
return "Database multi fetch failed";
}
});
});
您还可以使用闭包来确定重试范围,因此您的index
变量具有适当的作用域:
let delay = r => new Promise(r => setTimeout(r, ms));
function CallGetDB(retries) {
let index = retries;
return function inner(UID){
return getDynamodb(UID).then((data)=> {
console.log("check before if"+JSON.stringify(data));
return data;
}).catch(err => {
if(index--){
console.log("This is "+(retries-index)+" try to get data from db with UID.");
return delay(100).then(() => inner(UID));
} else {
console.log("Database multi fetch failed");
return "Database multi fetch failed";
}
});
};
}
您现在可以像这样使用:CallGetDB(2)(data)