1

I would like to fetch data from multiple files with a single async function. Currently my code is like this:

const fetchExternalData = async() => {
   const resp1 = await fetch('file1.txt');
   const resp2 = await fetch('file2.txt');
   return resp1.text(); // How could I return the content from file2.txt as well?
}

fetchExternalData().then((response) => {
  console.log(response); // Data from file1.txt
  // How could I access the data from file2.txt?
}

This way, I can work with the data from the first file, but how could I access the data from more files this way? Hope the question is understandable. Any help will be greatly appreciated.

2
  • 1
    Return an array of results: return [resp1.text() , resp2.text()] then use Promise.all() to wait on them Commented Jul 1, 2020 at 10:42
  • @slebetman dont answer questions in comments Commented Jul 1, 2020 at 10:54

2 Answers 2

3

Here's one way you could go about this using Promise.all:

const fetchExternalData = () => {
  return Promise.all([
    fetch("file1.txt"),
    fetch("file2.txt")
  ])
  .then(
    results => Promise.all(
      results.map(result => result.text())
    )
  )
}

Then, when calling your fetchExternalData function, you will get an array of items with data from both of your files:

fetchExternalData().then(
  (response) => {
    // [file1data, file2data]
  }
)

Here's an example:

const fetchExternalData = () => {
  return Promise.all([
    fetch("https://jsonplaceholder.typicode.com/todos/1"),
    fetch("https://jsonplaceholder.typicode.com/todos/2")
  ]).then(results => {
    return Promise.all(results.map(result => result.json()));
  });
};

fetchExternalData()
  .then(result => {
    // console.log(result);
  })
  .catch(console.error);

Alternatively, if you'd want to return an object instead of an array, you could do something like the following:

const fetchExternalData = items => {
  return Promise.all(
    items.map(item =>
      fetch(`https://jsonplaceholder.typicode.com/todos/${item.id}`)
    )
  )
  .then(
    responses => Promise.all(
      responses.map(response => response.json())
    )
  )
  // use `Array.reduce` to map your responses to appropriate keys
  .then(results =>
    results.reduce((acc, result, idx) => {
      const key = items[idx].key;
      
      // use destructing assignment to add 
      // a new key/value pair to the final object
      return {
        ...acc,
        [key]: result
      };
    }, {})
  );
};

fetchExternalData([
  { id: 1, key: "todo1" }, 
  { id: 2, key: "todo2" }
])
  .then(result => {
    console.log("result", result);
    console.log('todo1', result["todo1"]);
  })
  .catch(console.error);

References:

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you very much! This works, I can access the result array with result[0]. Is there a way to add keys to the result array, so I could access it with result['key1']?
@martin-hinze so you mean returning an object? See the edit
@martin-hinze and keys no, but you could just return an object like in my second example, or you could return an array of objects with the key that you want and you'd have to use the Array.find method to find the appropriate item, you wouldn't be able to do result["key1"] like you want it though
Thank you for the edit, this is more than I was hoping for. I will study your code meticulously and learn a lot from it!
@martin-hinze let me know if there are any questions or if there's a part that you don't understand, I will edit the question and provide more comments
1

return multiple values by putting it in an object. like this:

const fetchExternalData = async() => {
   const resp1 = await fetch('file1.txt');
   const resp2 = await fetch('file2.txt');
   return ({res1: resp1.text(), res2: resp2.text()});
}

2 Comments

Thank you for your support! I chose the answer from @goto1, because it is more flexible, but your's is helpful, too!
By the way, resp1.text() will return a Promise, so you'd need to do something like obj.rest1.then(...) to get the value that this Promise resolves with.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.