节点+ ES6:如何使用Promise.all与asynchronous请求?
我有一个名为fetchMerchantData
的方法,它调用3个其他的asynchronous方法。 我试图使用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"); }) } }); }
这里有一个调用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, }); }
我将如何同步呢?
==更新==
这是我的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}`); } }); }); }
这是一个使用promise的saveMerchant的例子。
function saveMerchant(merchant_id, access_token, locations) { return new Promise(function (resolve, reject) { const merchantRef = database.ref('merchants').child(merchant_id); const location_ids = locations.map(location => location.id); merchantRef.update({ access_token, location_ids, }, function (error) { if (error) return reject(error); resolve(); }); }); }
为了使上述更容易,有一个很好的Promise库叫做Bluebird,它有一个promisify工具,你可以应用到firebird的更新方法。
另外对于你的第二个问题,你使用forEach,蓝鸟有一个很好的实用function称为地图,你可以使用。