1

I am using a function fetchChain called with an array of objects, each object includes the url and other parameters to call another function fetchData to chain fetch-Calls. The async/await loop returns its results to the array I fed it with, like so (simplified):

fetchChain(array){
    const loop = async (items) => {
        for (let i = 0; i < items.length; i++) {
            await fetchData(items[i])
        }
    }

    return loop(array)
    .then(()=>{ return array })
}

I can wait for all promises/results to return like so:

fetchChain(prepareAjax)
.then((res)=> console.log(res) )
.then(()=> console.log('done') )

So why does the loop returns its results to the array it got fed with? There is no specific return or then which returns the results to the origin and I can't wrap my head around about what happens here.

As requested, the fetchDacta-function:

fetchData(obj){
    // some parameters get added, like so
    obj.timeout = obj.timeout   || 10000, [...];

    const fetchRetry = async (url, options, n) => {
        try {
            return await fetch(url, options)
                .then((response)=> return response.json());
        } catch(err) {
            if (n === 1) throw err;

            return await sleep(obj.delay)
                .then(()=> fetchRetry(url, options, n - 1));
        }
    };

    return fetchRetry(url, {}, obj.retries);
}
Pandora
  • 361
  • 3
  • 14
  • Please post the `fetchData` function. Does it modify the item (object?) that was passed to it? – Bergi Dec 09 '18 at 21:40
  • 3
    You should not need that `loop` function at all. Just write `async fetchChain(items) { for (const it of items) { await fetchData(it); } return items; }` – Bergi Dec 09 '18 at 21:42
  • Thanks for the shortened alternative. I added the fetchData to my question and yes, some parameters can get added inside fetchData, since I don't want to write all of them inside the config I'm passing to fetchChain or fetchData. (I shortened the fn as much as I could) – Pandora Dec 09 '18 at 21:51
  • `return loop(array).then(()=>{ return array })` you're returning the array you put in right there - why would you expect to get something else? – Matthew Herbst Dec 09 '18 at 21:52
  • @MatthewHerbst I'm actually getting something else => the promises/results I'm getting from fetchData. I'm expecting the original array to be returned when used like this, which isn't the case. – Pandora Dec 09 '18 at 21:54
  • You say the code above is simplified. Can you post the actual code? – Bergi Dec 09 '18 at 22:37
  • That would be a mess, since I moved from AJAX to fetch recently. Now I can't reproduce the behaviour and as expected and mentioned by MatthewHerbst the object I passed through gets returned. It was my mistake it seems, probably I overlooked something. Now I'm just pushing the returned promises into a separate array and returning this array similiar to your example. – Pandora Dec 09 '18 at 22:55

1 Answers1

2

I'm not sure if I understand the question correctly, but I think you're asking why the array argument in function fetchChain contains information assigned in fetchData.

For this you have to look at the difference of passing by reference vs passing by value. In JavaScript Objects and Arrays are automatically passed by reference to a function; which means array points to the same memory as items, and when you modify items you are modifying array.

This is a simple example to illustrate passing by reference

let changeMessage = (o) => o.message = 'world';
let obj = { message: 'hello'};
changeMessage(obj);
console.log(obj.message);
// Output: world

You can avoid modifying the array by cloning it first

  • My problem was, that array contained the results of fetchData and not the objects I used for iteration. I may have overlooked, that I modified the object I passed to fetchData somewhere inside it and then your answer would make sense. Since I can't reproduce the behaviour even when I go back to my first edit, I'm accepting your answer. – Pandora Dec 09 '18 at 23:11