2016-11-07 83 views
1

我有一個叫做fetchMerchantData的方法,它調用3個其他的異步方法。我正在嘗試使用Promise,以便在所有請求都完成但不起作用之前,它不會調用resp.direct(301, ...)節點+ ES6:如何使用Promise.all和異步請求?

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, 
    }); 
} 

我將如何同步呢?

== == 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

'saveMerchant'不返回任何東西? –

+0

nope它只是將它保存到firebase – Edmund

+1

我認爲布賴恩的觀點是,如果它沒有返回任何東西..那麼它不會返回一個承諾.. :)你的saveLocations&installWebhookForLocations返回承諾。? – Keith

回答

1

這裏是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(); 
    }); 
    }); 
} 

作出上述更容易,有一個名爲藍鳥一個很好的承諾庫,它有一個promisify工具,你可以應用到火鳥更新方法。

同樣對於你的第二個問題,你使用forEach,藍鳥有一個很好的實用函數叫做map,你可以用它來代替。

+0

ooo我可以做同樣的請求回調嗎? – Edmund

+0

是的,甚至還有一個基於promise的請求庫。這多做一些讓請求承諾的基礎,它也作爲承諾處理流。 - > https://www.npmjs.com/package/request-promise基本上任何有異步方法回調的東西都可以做成承諾。 – Keith

+0

讓承諾變得真的很棒的是,新的ES6特性,比如'async'和'await',可以承諾讓事情更好。 – Keith