2016-12-06 73 views
0

我使用Node.js的Node.js的 - 有回調反覆

我試圖做的是調用時觸發的承諾和它的回調函數返回一個鏈中的功能開發的JavaScript的API函數運行一個產品信息數組。

我想要做的就是根據需要多次運行此函數以形成JSON格式的產品列表。

但是這個產品列表需要在它被髮回給用戶之前創建,這是我掙扎的地方。

這是我具備的功能:

exports.findProduct = (ingredient, store, callback) => { 
      products.getProductData(ingredient, store) 
     .then(data => products.getProducts(data)) 
     .then(productList => products.filterProductData(productList)) 
     .then(selectedProduct => callback(null,selectedProduct))//get individual products and add to list 
     .catch(err => callback(err)) 
} 

我這樣稱呼它

products.findProduct(ingredient, 'Waitrose', (err, data) => { 

    if (err) { 
     //res.send(status.badRequest, {error: err.message}) 
    } else { 
     res.send(data) 
     res.end() 
    } 

}) 

res.send(data)從回調返回到服務器,但如果我要運行的發送數據這個函數再次和更新一個數組,然後才發送數組到服務器?

任何技巧的幫助將非常感激。

回答

1

基於承諾的可能實現,它允許getAllProducts遞歸調用自己。

exports.findProduct = (ingredient, store) => { 
    return new Promise((resolve, reject) => { 
     products.getProductData(ingredient, store) 
     .then(data => products.getProducts(data)) 
     .then(productList => products.filterProductData(productList)) 
     .then(selectedProduct => resolve(selectedProduct)) 
     .catch(err => reject(err)) 
    } 
} 



function getAllProducts(ingredientList, shopName) { 
    const allProducts = []; 
    return new Promise((resolve, reject) => { 
     products.findProducts(ingredientList, shopName) 
     .then(product => { 
      allProducts.push(...product); 

      if(/*need more products*/) { 
       getAllProducts(ingredientList, 'Tesco') 
       .then(newProducts => { 
        allProducts.push(...newProducts); 
        resolve(allProducts); 
       }) 
       .catch(err => reject(err)); 
      } else { 
       resolve(allProducts); 
      } 
     }) 
     .catch(err => reject(err)); 
    } 
} 

這樣調用...

getAllProducts(ingredientList, 'Waitrose') 
.then(products => { 
    res.send(products); 
    res.end(); 
}).catch(err => { 
    res.send(status.badRequest, {error: err.message}); 
    res.end(); 
}); 

編輯:

上述方法是有效的,如果您需要確定是否要基於之前調用的結果更多的呼叫。如果您知道前面需要撥打多個電話,例如如果你知道你要檢查特易購,維特羅斯和阿斯達,再有就是使用Promise.all

一個更簡單的方法
exports.findProduct = (ingredient, store) => { 
    return new Promise((resolve, reject) => { 
     products.getProductData(ingredient, store) 
     .then(data => products.getProducts(data)) 
     .then(productList => products.filterProductData(productList)) 
     .then(selectedProduct => resolve(selectedProduct)) 
     .catch(err => reject(err)) 
    } 
} 

function makeMultipleCalls() { 
    const stores = ['Waitrose', 'Tesco', 'Asda']; 
    const promises = []; 

    for (var store in stores) { 
     promises.push(product.findProduct(ingredientList, store); 
    } 

    Promise.all(promises) 
    .then(results => { 
     res.send(results.reduce((a,b) => a.concat(b))); 
     res.end(); 
    }) 
    .catch(err => { 
     //deal with error 
    }); 
} 
+0

非常感謝你的回答,只有一個小問題。在if語句中,'allProducts.push(newProducts)'將與第一個'allProducts.push(newProducts)'相同的元素推入。這導致類似'[product1,[product2,[product3]]]]'任何想法如何避免這個?乾杯 – al3

+0

我編輯了我的答案以使用spread(...)運算符,以便newProducts中的項目被添加到allProducts,而不是數組本身。 –

+0

經過反思,我還想知道是否有更簡單的方法來做到這一點,所以添加了一種不同的方法,可能適用於您的情況,也可能不適合您的情況。 –