Recursive Method to Iterate through Promises


Recursive Method for Iterating through Promises

A recursive function may be used to iterate through yielded Promises and return their fulfillment values back to the Generator function.


Notice how a recursive function is used to handle yields to Promises and yields to other values in any order:

function run(genFunc){
    const genObject= genFunc(); //creating a generator object

    function iterate(iteration){ //recursive function to iterate through promises
        if(iteration.done) //stop iterating when done and return the final value wrapped in a promise
            return Promise.resolve(iteration.value);
        return Promise.resolve(iteration.value) //returns a promise with its then() and catch() methods filled
          .then(x => iterate(genObject.next(x))) //calls recursive function on the next value to be iterated
          .catch(x => iterate(genObject.throw(x))); //throws an error if a rejection is encountered
    }

    try {
        return iterate(genObject.next()); //starts the recursive loop
    } catch (ex) {
        return Promise.reject(ex); //returns a rejected promise if an exception is caught
    }
}


The run() function shown above takes in a Generator function as an argument and uses the recursive iterate() function to process through all of the Generator function's yield statements. If a Promise is yielded, the fulfillment value of that Promise is sent back to the Generator function. If an integer, string or object is yielded, then those values are sent back as is to the Generator function.


Notice how the run() function is used to process a Generator function:

function *gen(){

    let post1Stream = yield fetch("https://jsonplaceholder.typicode.com/posts/1");

    let post1 = yield post1Stream.json();
        console.log(post1.title); //post1.title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit"

    let post2Stream = yield fetch("https://jsonplaceholder.typicode.com/posts/2");

    let post2 = yield post2Stream.json();
        console.log(post2.title); //post2.title = "qui est esse"

    let number = yield 12345;
        console.log(number) //number = 12345

    let string = yield "abc";
        console.log(string) //string = "abc"

    let obj = yield {id:123,name:"xyz"};
        console.log(obj) //obj = Object {id:123,name:"xyz"}

    let a = yield 54434337746;
        console.log(a);
    return "done";
}

run(gen).then(x => console.log(x)) //logs "done"
        .catch(x => console.log(x.message));


If a rejected Promise is yielded, the run() method will stop iterating through the Generator function and return a rejected Promise.


Notice how the run() method handles rejected promises:

function *gen(){

    var post1Stream = yield fetch("https://jsonplaceholder.typicode.com/posts/1");
    var post1 = yield post1Stream.json();
    console.log(post1.title); 
    //post1.title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit"
    var post2Stream = yield fetch("https://jsonplaceholder.typicode.com/posts/2");
    var post2 = yield post2Stream.json();
    console.log(post2.title);
    //post2.title = "qui est esse"

    var error = yield Promise.reject(Error("error message!"));
    //error thrown here, generator function terminates

    var number = yield 12345;
    console.log(number); //doesn't occur because an earlier promise was rejected 

    return 'done'; //doesn't occur because an earlier promise was rejected

}

run(gen).then(x => console.log(x))
        .catch(err => console.log(err.message); //logs "error message!" from the rejected Promise

results matching ""

    No results matching ""