Generators: Método recursivo para iterar utilizando Promises

Generators: Método recursivo para iterar utilizando Promises

¿Cómo utilizar una función recursiva para retornar valores de funciones generator?

Una función recursiva puede ser utilizada para iterar a través de yielded Promises y retornar valores a la función Generator.

function run(funGenerator) {
    // provee una función generator como argumento
    var og = funGenerator(); // crea un nuevo object generator a traves de la función provista
    function iterador(iteracion) {
        // funcion recursiva para iterar a través de los promises
        if (iteracion.done) {
            // si se completo la iteración
            return Promise.resolve(iteracion.value); // retornar el valor final de la iteración
        }
        return Promise.resolve(iteracion.value) // crea un promise resuelto con el valor de la iteracion
            .then((x) => iterador(og.next(x))) // llama de forma recursiva la función iteradora
            .catch((x) => iterador(og.throw(x))); // lanza un error si un fallo es encontrado
    }
    try {
        return iterador(og.next()); // inicia el loop recursivo
    } catch (ex) {
        return Promise.reject(x); // retorna el promise con la excepción capturada
    }
}

La función run() toma una función Generator como argumento y utiliza la función recursiva iterador() para procesar a través de todas las sentencias yield del Generator. Si una Promise es yielded, el valor valor de esta es enviado de vuelta a la función Generator. Si un entero, string un objeto son yielded entonces esos valores son enviados de vuelta a la función Generator.

Vea como la función run() es utilizada para procesar una función Generator.

function* gen() {
    var s1 = yield fetch("https://jsonplaceholder.typicode.com/posts/1");
    var j1 = yield s1.json();
    console.log(j1.title); // imprime el title del request
    var s2 = yield fetch("https://jsonplaceholder.typicode.com/posts/2");
    var j2 = yield s2.json();
    console.log(j2.title); // imprime el title del segundo request

    var matricula = yield 1006218;
    console.log(matricula);

    var nombre = yield "John";
    console.log(nombre);

    var obj = yield { nombre: "John Doe", edad: 25 };
    console.log(obj);

    return "completado";
}

run(og)
    .then((x) => console.log(x)) // "completado"
    .catch((e) => console.log(e.message)); // en caso de una excepción imprime el mensaje

Si una Promise marcada con yield es rechazada, el método run() detendrá la iteración a través de la función Generator y retornará una Promise.