Search code examples
javascriptpromisees6-promisebluebirdrequest-promise

write a while loop using promises using return values within the next promise


I have read all the questions on SO about this subject but I'm still stuck because the condition function in promiseWhile does not take a parameter.

My use case is the following. I am trying to query some information for some date (start_date). I do not know whether there is info for start_date in my db so I want to check for that. If there is no data, I want to query the day before and keep doing that until there is data. (I know the promise while loop is not the best way to do that but I want to learn how to do it nonetheless)

Here is my code so far

let start_date = DateTime.fromFormat(req.body.date, "yyyy-MM-dd");
let date_promise = (the_date) => {
    let the_req = {
        date: the_date
    };
    return db.query(the_req);
};

let promiseWhile = Promise.method(function (condition, action) {
    if (!condition()) return;
    return action().then(promiseWhile.bind(null, condition, action));
});

promiseWhile(
    (body) => {return body.rows.length > 0},
    () => {
        start_date = start_date.minus(luxon.Duration.fromObject({days: 1}))
        return date_promise(start_date);
    },
).then((result) => {
    // start_date ... 
    // do something with the date I've obtained
});

date_promise return a promise.

In my promiseWhile condition I am trying to test that body.rows contains something with body being the parameter of the .then function after the result of date_promise resolves. (date_promise(some_date).then((body) => {...})).

I am not sure how to proceed from there. Any help welcome.


Solution

  • Promise.method is an older version of async functions. With that in mind and a few syntax corrections, your code would look like this:

    let start_date = DateTime.fromFormat(req.body.date, "yyyy-MM-dd");
    
    let date_promise = (the_date) => {
        let the_req = {
            date: the_date
        };
        return db.query(the_req);
    };
    
    const myAction = date => () => date_promise(date);
    
    let promiseWhile = async function (condition, action) {
        const queryResults = await action();
        if (!condition(queryResults)) {
          start_date = start_date.minus(luxon.Duration.fromObject({days: 1}));
          return promiseWhile(condition, myAction(start_date));
        } else {
          return queryResults;
        }
    };
    
    promiseWhile(
        body => body.rows.length > 0,
        () => {
            return myAction(start_date);
        },
    ).then(result => { // The result you'll get here is queryResults.
        // start_date ... 
        // do something with the date I've obtained
    });