如何在 .map 中返回異步函數? (How do I make an asynchronous function return in .map?)


問題描述

如何在 .map 中返回異步函數? (How do I make an asynchronous function return in .map?)

我試圖在 fetchPersons 函數的其餘部分執行之前讓 fetchIDFromPerson 函數返回並將返回的值分配給 ID。它只返回未定義,因為它是異步的。我該怎麼做才能讓它工作?謝謝。

const fetchIDFromPerson = name => {
  axios
    .get(`https://swapi.co/api/people/?search=${name}&format=json`)
    .then(response => extractImgIDFromURL(response.data.results[0].url))
    .catch(error => console.error(error));
};

let body;

const fetchPersons = (query, imgID) => {
  SWAPIGraphQL.post("", { query })
    .then(result => {
      const { allPersons } = result.data.data;
      return (body = allPersons.map(person => {
        const ID = fetchIDFromPerson(person.name); //This returns undefined!
        return {
          ...person,
          imgID: ID //needs to be assigned a value from fetchIDFromPerson
        };
      }));
    })
    .catch(error => console.error(error));
};

fetchPersons(GET_PERSONS_DATA);

參考解法

方法 1:

You need to make a number of changes to properly use the promises that your asynchronous code return:

  1. return the axios promise to the caller in fetchIDFromPerson().
  2. rethrow error in .catch() after logging it so the caller sees the error
  3. return the return SWAPIGraphQL.post() promise to the caller in fetchPersons().
  4. Get rid of the body variable. You don't want side effect programming, particular with asynchronous code. Communicate back results through returned promises.
  5. Use Promise.all() on the results of the .map() so you know when all those promises are done.
  6. When calling fetchPersons() use the returned promise to get the resolved value.
  7. Inside the .map() return the promise from fetchIDFromPerson().
  8. Add a .then() to where you call fetchIDFromPerson() where you can return the combined data structure with person and ID in it.
  9. Change response.data.results[0].url to response.results[0].url to match the data structure you're getting back.

Here's the fixed up code:

const fetchIDFromPerson = name => {
  return axios
    .get(`https://swapi.co/api/people/?search=${name}&format=json`)
    .then(response => extractImgIDFromURL(response.results[0].url))
    .catch(error => {
        // log and rethrow
        console.error(error);
        throw error;
    });
};


const fetchPersons = (query, imgID) => {
  return SWAPIGraphQL.post("", { query })
    .then(result => {
      const { allPersons } = result.data.data;
      return Promise.all(allPersons.map(person => {
        return fetchIDFromPerson(person.name).then(ID => {
            return {
              ...person,
               imgID: ID
            };
        });
      }));
    })
    .catch(error => {
        // log error and rethrow
        console.error(error);
        throw error;
    });
};

fetchPersons(GET_PERSONS_DATA).then(results => {
    console.log(results);
}).catch(err => {
    console.log(err);
});

You can simplify fetchPersons() a bit by using async/await and not logging the error as many separate places:

const fetchPersons = async (query, imgID) => {
    const result = await SWAPIGraphQL.post("", { query });
    const { allPersons } = result.data.data;
    return Promise.all(allPersons.map(async (person) => {
        const ID = await fetchIDFromPerson(person.name);
        return {
          ...person,
           imgID: ID
        };
    }));
};

(by Aleksandar Zdravkovskijfriend00)

參考文件

  1. How do I make an asynchronous function return in .map? (CC BY‑SA 2.5/3.0/4.0)

#fetch #javascript #Promise #asynchronous






相關問題

mysql fetch 中的 $row 是什麼類型的變量? (What kind of variable is $row from a mysql fetch?)

如何在 PHP 中使用 bind_params 正確獲取數據到數組 (How to correctly fetch data to array with bind_params in PHP)

使用 JavaMail 加速電子郵件檢索 (Speed up email retrieval with JavaMail)

使用 eclipselink 從多個表中獲取數據 (Fetch data from multiple tables using eclipselink)

如何在 Webassembly 中獲取 JSON 文件 (How to Fetch a JSON file in Webassembly)

mysqli(a,b,c,d)->query(sql)->fetch_assoc() 究竟是如何工作的? (How exactly does mysqli(a,b,c,d)->query(sql)->fetch_assoc() work?)

如何在 .map 中返回異步函數? (How do I make an asynchronous function return in .map?)

如何僅在響應中的 onclick 事件後映射 json 列表? (How to map a json list only after an onclick event in react?)

在第二個 API 中使用來自第一個 API 的信息 - React (Using information from the first API in the second one - React)

使用 Jest 測試框架調用 fetch(url) 時如何根據 url 模擬變量響應? (How to mock variable responses based on the url when fetch(url) is called using the Jest testing framework?)

函數不返回對像以供 .then 使用 - 但能夠 console.log 對象,並明確返回它 (Function not returning object for .then to work with - but able to console.log the object, and am explicitly returning it)

fetch api - 400 加載資源失敗 (fetch api - 400 failed to load resource)







留言討論