2015-11-05 64 views
3

我用的帆,水線和異步庫如何使一個for循環的工作與async.parallel()

function Outerfunction(listOfProducts) { 
    var salesOrderId = 1; //some id 
    var prom = []; 
    for (var i = 0; i < listOfProducts.length; i++) { 
    var qty = listOfProducts[i].quantity; 
    var prod = listOfProducts[i].productName; 
    var update = function(qty, prod, SalesOrderId) { 
     CardImages.update({ 
      where: { 
      productName: prod, 
      isSold: false, 
      readyToSell: true 
      } 
     }, { 
      order: SalesOrderId, 
      isSold: true 
     }) 
     .exec(function(err, updatedRecords) { 
      if (err) return err; 
      return updatedRecords; 
     }); 
    } 
    prom.push(update); 
    } 
    async.parallel(prom, function(err, result) { 

    //this callback never gets called 
    console.log("database calls done"); 
    }); 
} 

我試圖用一個for循環來更新數據庫,此代碼工作正常,並更新數據庫,但但我的回調async.parallel不會在所有記錄更新時被調用。

+2

'async.parallel'確實需要一個*函數*的數組。什麼'exec'返回?假設你已經用[promise]標記了這個,你似乎期望它返回一個promise(只有當你沒有回調'exec'時)纔會返回一個promise--所以你想使用'Promise.all(prom).then ...)',並且不應該使用async.js! – Bergi

+1

或 堅持'async', 清除承諾的任何概念, 將成員名稱「proms」更改爲「tasks」, 修改推送到'tasks'的函數以符合[文檔](https:// github.com/caolan/async#parallel) –

+0

而不是使用for循環我用了一個函數,一個計數器和一個回調,但它很慢,我仍然在尋找一個解決方案:) –

回答

2

您正在查找的函數是async.map,它將對數組中的每個元素應用異步函數,並用結果數組回調。我不能對此進行測試,但這樣的事情應該工作:

function OuterFunction(listOfProducts) { 
    var salesOrderId = 1; // some id 

    async.map(listOfProducts, function (product, done) { 
    // for each product, update its DB entry 
    CardImages.update({ 
     productName: product.productName, 
     isSold: false, 
     readyToSell: true 
    }, { 
     order: salesOrderId, 
     isSold: true 
    }).exec(done); // indicate that async work is done 
    }, function (err, result) { 
    // all finished 
    console.log('database calls done'); 
    }); 
} 

請注意,此解決方案完全不使用的承諾。這只是基於回調的異步工作。


我還沒有和水線的工作,但我很快的(而壞)文檔中找到依據,這也是一個可能的解決方案:

function OuterFunction(listOfProducts) { 
    var salesOrderId = 1; // some id 
    // extract product names 
    var productNames = listOfProducts.map(function (product) { 
    return product.productName; 
    }); 

    // update in bulk 
    CardImages.update({ 
    productName: productNames, 
    isSold: false, 
    readyToSell: true 
    }, { 
    order: salesOrderId, 
    isSold: true 
    }).exec(function (err, results) { 
    // all finished 
    console.log('database calls done'); 
    }); 
} 

轉換爲SQL,第一個解決方案將發射(大致)

UPDATE table SET isSold = TRUE, readyToSell = FALSE 
WHERE productName = 'product 1' AND isSold = FALSE AND readyToSell = TRUE; 

UPDATE table SET isSold = TRUE, readyToSell = FALSE 
WHERE productName = 'product 2' AND isSold = FALSE AND readyToSell = TRUE; 

UPDATE table SET isSold = TRUE, readyToSell = FALSE 
WHERE productName = 'product 3' AND isSold = FALSE AND readyToSell = TRUE; 

... 

和第二將發射的更有效的

UPDATE table SET isSold = TRUE, readyToSell = FALSE 
WHERE productName IN ('product 1', 'product 2', 'product 3', ...) 
    AND isSold = FALSE AND readyToSell = TRUE; 
+0

哇...謝謝你的答案 –