Node + ES6:如何将Promise.all与异步请求一起使用?

时间:2016-11-07 20:45:26

标签: javascript node.js

我有一个名为fetchMerchantData的方法,它调用其他3个异步方法。我正在尝试使用Promise,以便在所有请求完成后它不会调用resp.direct(301, ...),但它不起作用。

function fetchOauth2Token(authorizationCode, resp) {
  ...
  request({
    url: `https://connect.squareup.com/oauth2/token`,
    method: "POST",
    json: true,
    headers: oauthRequestHeaders,
    form: oauthRequestBody,
  }, (error, oauthResp, body) => {
    if (body.access_token) {
      Promise.resolve(fetchMerchantData(body.access_token, body.merchant_id)).then(() => {
        console.log("last!"); //<--------------------- this is printing first
        resp.redirect(
          301,
          `myurl.com/blah`
        );
      });
      ;
    } else {
      // TODO find out what to do on failure
      resp.redirect(301, `myurl.com/?error=true`);
    }
  })
}

function fetchMerchantData(access_token, merchant_id){
  const updates = {};
  request({
    url: `https://connect.squareup.com/v1/me/locations`,
    method: "GET",
    json: true,
    headers: {
      Authorization: `Bearer ${access_token}`,
      Accept: 'application/json',
      "Content-Type": "application/json",
    },
  }, (error, response) => {
    if (!error) {
      const locations = response.body;

      Promise.all([
        saveMerchant(merchant_id, access_token, locations),
        saveLocations(merchant_id, locations),
        installWebhookForLocations(access_token, locations),
      ]).then(values => {
        console.log("first!"); //<--------------------- this is printing last
        return Promise.resolve("Success");
      })
    }
  });
}

以下是调用firebase的saveMerchant方法示例:

function saveMerchant(merchant_id, access_token, locations) {
  const merchantRef = database.ref('merchants').child(merchant_id);
  const location_ids = locations.map(location => location.id);

  merchantRef.update({
    access_token,
    location_ids,
  });
}

我如何同步?

== UPDATE ==

这是installWebhookForLocations方法的外观:

function installWebhookForLocations(access_token, locations){
  const locationIds = locations.map(location => location.id);
  locationIds.forEach((locationId) => {
    request({
      url: `https://connect.squareup.com/v1/${locationId}/webhooks`,
      method: "PUT",
      json: true,
      headers: {
        Authorization: `Bearer ${access_token}`,
        Accept: 'application/json',
        "Content-Type": "application/json",
      },
      body: ["PAYMENT_UPDATED"],
    }, (error) => {
      if (!error){
        console.log(`Webhook installed for ${locationId}`);
      }
    });
  });
}

1 个答案:

答案 0 :(得分:1)

以下是使用promise的saveMerchant示例。

targetSdkVersion

为了使上述更容易,有一个很好的Promise库叫做Bluebird,它有一个promisify实用程序,你可以应用于firebird更新方法。

另外,对于你的第二个问题,你使用forEach,bluebird有一个很好的实用函数叫做map,你可以使用它。