Skip to content Skip to sidebar Skip to footer

How Can Asynchronous Method In Recursion Return Result Correctly?

I asked question about how to run asynchronous method in loop. And I am now doing it in something like recursion. How can asynchronous method in loop executed in sequence? But now

Solution 1:

Wrapping GetDynamodb(UID) in a new Promise is an anti-pattern since it returns a promise.

Following adds a retries parameter with a default to CallGetDB() and either returns a new promise in the catch() when retries are within limits.... or throws a new error to get caught in following 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*/ );

Solution 2:

Your promise isn't resolving in the event of an error and an index lower than 2. Here:

if(index++ < 2){
  console.log("This is "+(index+1)+" try to get data from db with UID.");
  setTimeout(function(){CallGetDB(UID);},100);
}

At that point, your promise will never fulfill or reject as the original promise never gets fulfilled and can't resolve the JSON data nor does it hit your else branch.It becomes an unresolved promise (a promise stalled indefinitely). It will work in the event that GetDynamodb fulfills on the first attempt though.

You can fix this by fulfilling the promise inside the if branch:

setTimeout(function(){resolve(CallGetDB(UID));},100);

That being said, you probably shouldn't be wrapping promises like this. This is a somewhat similar approach to yours:

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";
        }
    });
});

You can also use a closure for scoping retries, so you have a proper scope for your index variable:

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";
            }
        });
    };
}

Which you can now use like: CallGetDB(2)(data)


Post a Comment for "How Can Asynchronous Method In Recursion Return Result Correctly?"