Skip to content
Advertisement

How do i use fetch with a result from a fetch in the same function with sync await

the promise creates an array like this, taken from the console:

(6) [Promise, Promise, Promise, Promise, Promise, Promise]
0: Promise {<fulfilled>: undefined}
1: Promise {<fulfilled>: undefined}
2: Promise {<fulfilled>: undefined}
3: Promise {<fulfilled>: undefined}
4: Promise {<rejected>: SyntaxError: Unexpected token < in JSON at position 0}
5: Promise {<fulfilled>: undefined}
length: 6

which cannot be used.

the code is this:

export default async function getData() {
  let response = await request('http://localhost:2000/api/ves.json').then((data) => fetch(data));
  
  let store = await response.json();
  let list = await  store.map(async (input, index)=>{
    let details = await request(`http://localhost:2000/api/${input.id}.json`).then((data) => fetch(data));
   let foo = await details.json();
   console.log(foo);
    input = await {...input, ...foo};
  });
  
  return  list;
}

at the point, the list is returned (when the useData function is used) the mapping seems to have not finished. So it returns “promise” instead of the list it should.

The aim is to combine the objects. This is don’t by using information from the first object (in an array of objects) to get information from the second object. Then pushing the second object into the first one at the same point in the array the information was retrieved to get the second object.

The same problem appears if I also do either

    input = await {...input, ...foo};
  }});
  await Promise.all(list)
  return  list;

or

   console.log(foo);
    input = await {...input, ...foo};
  }});
  let fish = await Promise.all(list)
  return  fish;

gives the console error

(6) [undefined, undefined, undefined, undefined, undefined, undefined]

this useData function is called in a react page through this.

  const [ves] = useData();

      useEffect(()=>{
    
        console.log(ves);
      },[ves])

Advertisement

Answer

You aren’t returning anything in your .map function. You also need to use Promise.all() on the array of promises that the .map will return (since the function you are passing it is async which means it will always wrap the return in a Promise.

Also, input = await {...input, ...foo}; doesn’t really make sense to me. You await promises, not synchronous value assignments.

export default async function getData() {
  let response = await request('http://localhost:2000/api/ves.json').then((data) => fetch(data));

  let store = await response.json();
  let list = store.map(async(input, index) => {
    let details = await request(`http://localhost:2000/api/${input.id}.json`).then((data) => fetch(data));
    let foo = await details.json();
    console.log(foo);
    // Have to return something within the .map
    return {
      ...input,
      ...foo
    };
  });
  
  // Have to wait for all the mapped promises to resolve
  const resolvedList = await Promise.all(list);

  return resolvedList;
}

There is another issue in that you don’t .catch any of the errors that might be happening during the fetch. I see

Promise {<rejected>: SyntaxError: Unexpected token < in JSON at position 0}

Which means one of the API is returning HTML instead of JSON which causes .json() to throw.


Array.prototype.map() is sort of a combinatorial function. It iterates an array, processes the values of that array, and returns a new array of the same size with processed values. Think of it literally as a way to map values to another value.

In your example, you are trying to map network responses to additional network requests. If you don’t return, the implication is “I don’t care about the processed values”, at which point you might as well use .forEach.

You do care about the responses. So you should return values in the map function (the return values are promises that resolve to data) and then Promise.all() that mapped array so that it unwraps to an array of actual data.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement