1. ホーム
  2. javascript

map内で非同期関数を呼び出す最適な方法とは?

2023-09-04 19:33:10

質問

配列にマッピングし、新しいオブジェクトの戻り値の1つに対して、非同期呼び出しを行う必要があります。

var firebaseData = teachers.map(function(teacher) {
  return {
    name: teacher.title,
    description: teacher.body_html,
    image: urlToBase64(teacher.summary_html.match(/src="(.*?)"/)[1]),
    city: metafieldTeacherData[teacher.id].city,
    country: metafieldTeacherData[teacher.id].country,
    state: metafieldTeacherData[teacher.id].state,
    studioName: metafieldTeacherData[teacher.id].studioName,
    studioURL: metafieldTeacherData[teacher.id].studioURL
  }
});

その関数の実装は次のようになります。

function urlToBase64(url) {
  request.get(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      return "data:" + response.headers["content-type"] + ";base64," + new Buffer(body).toString('base64');
    }
  });
}

これを行うための最良のアプローチが何なのかはっきりしません...約束?ネストされたコールバック?ES6またはES7で何かを使用し、その後Babelでトランスパイルする?

これを実装するための現在の最良の方法は何ですか?

どのように解決するのですか?

一つの方法として Promise.all (ES6) .

この回答はNode 4.0+で動作します。それ以前のバージョンでは、Promiseのポリフィルやライブラリが必要になります。また、私はES6の矢印関数を使用していますが、これは通常の function に置き換えることができます。

このテクニックは、手動で request.get をPromiseでラップしています。のようなライブラリを使うこともできます。 リクエストプロミス .

function urlToBase64(url) {
  return new Promise((resolve, reject) => {
    request.get(url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        resolve("data:" + response.headers["content-type"] + ";base64," + new Buffer(body).toString('base64'));
      } else {
        reject(response);
      }
    });
  })
} 

// Map input data to an Array of Promises
let promises = input.map(element => {
  return urlToBase64(element.image)
    .then(base64 => {
      element.base64Data = base64;
      return element;
    })
});

// Wait for all Promises to complete
Promise.all(promises)
  .then(results => {
    // Handle results
  })
  .catch(e => {
    console.error(e);
  })