2017-05-06 153 views
0

我遇到節點的異步性質問題。有人可以用這段代碼來幫助我。由於各種原因,我一次只能插入1行到我正在使用的數據庫中。實際上,如果我可以添加一個短暫的延遲來每秒只向數據庫中插入1行,那將會更好。Javascript/Node.js異步循環

這是我的js代碼的一小部分。

console.log('*** Inserting Records ***') 
insertPromises = [] 
_.each(dbRecords, function (item) { 
    var insertItem = buildRecord(item) 
    insertPromises.push(conn.create(insertItem)) 
}) 
Promise.all(insertPromises).then(function (res) { 
    _.each(res, function (item) { 
     if (!item.success) { 
      console.log("### Error ### " + JSON.stringify(res[i].errors)) 
     } 
    }) 
    console.log('*** Inserted ' + res.length + ' Contacts') 
}) 

我的主要問題是我怎麼能強制循環等待conn.create承諾繼續循環之前解決?有沒有辦法讓循環速度減慢到每秒1次?

+0

是那個答案有幫助嗎? – Jbird

回答

1

而不是使用上面發佈的遞歸代碼,您可以檢查async/await模型。

使用,這將是的一個例子:

async function processRecords(dbRecords) { 

    for (let item of dbRecords) { 
     try { 
      let insertItem = buildRecord(item) 
      await conn.create(insertItem) 
      await delay(1000) 
     } catch (e) { 
      //handle error... 
     } 
    } 

} 

function delay(ms) { 
    return new Promise((resolve) => setTimeout(resolve, ms)) 
} 

processRecords(dbRecords) 

這是ES7代碼,你需要babel編譯器來改變它。

如果你很難跟上承諾並且想要堅持類似sync的代碼,那麼使用類似的東西可能會更好。

+0

你不需要巴貝爾來改造它;該語法在nodejs 7.6及以上版本中完全支持。 :) –

+0

不錯,感謝提的是!但是這個問題沒有提到他正在使用的nodejs版本,所以也許babel是必需的! –

+0

不錯...我喜歡這種方法,但我正在獲取UnhandledPromiseRejectionWarning。我的代碼幾乎與您在答案中的含義完全相同。 fyi - 它的工作完美...只是在退出循環時拋出錯誤。 – Todd

1

一個簡單的解決方案是跟蹤「插入計數」,即當前成功插入記錄的數量。這將是你的數組指針。使用一種方法來創建每個單獨的承諾,並在每次成功響應時將「插入計數」增加1。

let insertCount = 0; 

function insertNextRecord() { 
    conn.create(buildRecord(dbRecords[insertCount]).then(function(res){ 
     insertCount += 1; 
     insertNextRecord(); 
    }).catch(function() { 
     console.log('Error while inserting record ' + insertCount); 
    }); 
} 

insertNextRecord(); 

這不是測試,我在調查你不顯示代碼的幾個假設。

這個例子假設:

  • dbRecords是一個數組
  • conn.create返回一個承諾對象

明確添加的延遲,你可以在then方法,像這樣內使用超時:

let insertCount = 0; 

function insertNextRecord() { 
    conn.create(buildRecord(dbRecords[insertCount]).then(function(res){ 
     insertCount += 1; 
     setTimeout(function() { 
      insertNextRecord(); 
     }, 500); 
    }).catch(function() { 
     console.log('Error while inserting record ' + insertCount); 
    }); 
} 

insertNextRecord(); 

我也應該說這是不幸的,你必須這樣做。處理很多插頁時,這將非常緩慢。

+1

它不起作用,像當前代碼,它有遞歸,這個塊將按順序運行每個db查詢。要增加延遲,有人可能會簡單地在內部insertNextRecord() –

+0

無添加的setTimeout,你目前的代碼使用Promise.all它等待所有'insertPromises'承諾的解決本身之前解決。換句話說,在所有插入請求完成之前,這個承諾不會解決。我提供的示例在轉到下一個之前等待當前的請求解決。你不想明確說明「延遲」 - 這就是所謂的競爭條件。你只是想知道請求'1'何時完成,然後請求'2' - 並且當請求'B'完成後,請求'3'...等等。 – Jbird