Sequential fetch and 5 ways to solve


At technical interviews, in addition to checking theoretical knowledge, it is customary to set tasks to assess the level of practical knowledge of the candidate, his ability to write code, and the ability to think logically and algorithmically. Often, this list includes algorithmic problems. Everyone has become accustomed to them and, when preparing, first of all, they look at them. The list is long, but the main thing that is most often found looks something like this:


  • factorial
  • Fibonacci numbers
  • uniqueness of array elements
  • checking for parentheses within the text
  • (mergeSort, insertionSort, bubbleSort, quickSort)
  • ( / / )

, 70 JavaScript, , , , ( , ).


, :



, , .


:


, :


:
fetch(url1) => fetch(url2, resultsUrl1) => fetch(url3, resultsUrl2)

-
compose(res2 => fetch(url3, res2), res1 => fetch(url2, res1), () => fetch(url1))

?

, ( ):


  • async/await

, , ( reduce, ).


, ; , - ; ; .


, . . , , , .


, reduce , Array. :


  • reduce

, fetch , :


function fakeFetch (url, params='-') {
    //           
    console.log(`fakeFetch to: ${url} with params: ${params}`);
    return new Promise(resolve => {
        setTimeout(() => resolve(`${url} is DONE`), 1000);
    })
};

( ):


const urls = ['url1', 'url2', 'url3'];

( 1), . then().then().then() await; await; await; .


, callback. :


fetchSeries(result => console.log(`result: ${result}`))

, . , , .



, , . , , , .


function generatorWay(callback) {
    function* generateSequence() {
        let results;
        for (let i = 0; i < urls.length; i++) {
            results = yield fakeFetch(urls[i], results);
        }
        return results;
    }
    function execute(generator, yieldValue) {
        let next = generator.next(yieldValue);
        if (!next.done) {  
            return next.value
                .then(result => execute(generator, result));
        } else {
            callback(next.value);
        }
    }
    execute(generateSequence())
}


:


  • generateSequence yield' , .
  • execute(generator), next, — , , , next.
  • execute , callback.


, while:


async function asyncGeneratorWay(callback) {
    async function* generateSequence() {
        let results;
        for (let i = 0; i < urls.length; i++) {
            results = yield await fakeFetch(urls[i], results);
        }
        return results;
    }
    let generator = generateSequence();
    let result;
    while (!result || !result.done) {
        result = await generator.next(result && result.value);
    }
    callback(result.value);
}


( ).


for await of , 2.


Async/await


. , async/await. , async, .


async function asyncAwaitWay(callback) {
    const series = async () => {
        let results;
        for (let i = 0; i < urls.length; i++) {  
            results = await fakeFetch(urls[i], results);
        }
        return results;
    }
    const result = await series();
    callback(result);
}


fakeFetch await;


Recursion


, reduce ( ), recursion . . , :


function recursionWay(callback) {  
    const recursion = (arr = [], promise = Promise.resolve()) => {
        if (!arr.length) { 
            return promise;
        }
        const [url, ...restUrls] = arr;
        return promise
            .then(res => recursion(restUrls, fakeFetch(url, res)));
    }
    recursion(urls)
        .then(result => callback(result));
}


shift , . .


Promise.resolve(), -, , , .


Reduce


, , . , , .


function reduceWay(callback) {
    urls
        .reduce((accum, item) => {
            return accum
                .then(res => fakeFetch(item, res))
        }, Promise.resolve())
        .then(result => callback(result));
}


:


  • fakeFetch then;
  • , Promise.resolve(), -, , (Promise) , . :

function reduceWay(callback) {
    urls
        .reduce((accum, item) => {
            if (!accum) {
                return fakeFetch(item);
            }
            return accum
                .then(res => fakeFetch(item, res));
        })
        .then(result => callback(result));
}

2 .



. , :


.
reduce61
async/await9x1.5
recursion10x1.67
()13x2.17
17x2.83

"", , reduce. , ( ). , , :


const reduceWay = callback => urls.reduce(
    (acc, item) => acc.then(res => fakeFetch(item, res)),  
    Promise.resolve())
    .then(result => callback(result));  
}


, , , .


, — . async/await — , . reduce / .


, , … .



Generators


Asynchronous Generators


Array: iterate over reduce


Recursion


Async / await


Promises


Promise Chain


UPD I make some adjustments to the async / await method, following the comments. Indeed, one could shorten the method and give it greater visibility with for of:


async function asyncAwaitWay(callback) {
    let results;
    for (const url of urls) {  
        results = await fakeFetch(url, results);
        }
    callback(result);
}

All Articles