Pages

搜尋此網誌

2014年7月27日 星期日

javascript: promise with reduce

javascript: promise with reduce

最近工作上使用到常常聽到的 map reduce,相關使用說明,可參考下列連結:

enter image description here

若是一般的資料處理利用 map reduce 非常好用,可以善用平行處理來加快處理速度,不過很多情況下,我們希望可以搭配 promise 使用,比如說查詢資料,或資料更新,有時希望 reduce 可以依序執行,有時希望可以平行處理,將分別介紹兩種狀況使用方式。

其中 prmise 使用的是 Q promise,相關使用說明可參考連結。

依序處理

  promiseTrackReportUpdate = (promise, trackReportGroup) ->
    return promise.then (results) ->
      defer = Q.defer()
      TrackReportService.findOrCreateTrackReport(trackReportGroup)
      .then (targetTrackReport) ->
          results.push targetTrackReport
          defer.resolve results
      return defer.promise

  trackReportSorted.reduce promiseTrackReportUpdate, Q([])
  .then (finalResults) ->
      return finalResults

TrackReportService.findOrCreateTrackReport(trackReportGroup) 已實作為 promise,故一旦該函式執行完可使用 .then 接續下一步。

Q([]): 作為 promise 初始值,第一次的 return promise.then (results) -> 中的 results 值為 [],而 results 將會依序被處理,透過每次的 defer.resolve results 往下一個 promise.then (results) 傳遞,直到最後取得完整的處理結果 finalResults

平行處理

  promiseTrackReportUpdate = (results, trackReportGroup) ->
    promise = TrackReportService.findOrCreateTrackReport(trackReportGroup)
    results.push promise
    return results

  promiseTrackReportUpdate = trackReportSorted.reduce promiseTrackReportUpdate, []
  Q.allSettled promiseTrackReportUpdate
  .then (finalResults)-> 
    finalResults = finalResults.map (result) -> return result.value
    return finalResults

與依序處理不同,將每次 reduce 作為一個獨立的 promise push 到陣列,reduce 完的結果將存入 promiseTrackReportUpdate。

因為是平行處理,所以 reduce 的起點是 [],而不是 Q([])

最後透過 Q.allSettled,一旦所有的 promise 都處理完就可以將處理結果取出,利用 map 的特性,取出最後的處理結果

結論

在程式開發的過程中總會需要依序處理,比如說資料累加需要依序進行,或是處理訊息型的資料,可以平行處理,來加快處理速度,不論哪種應用,能夠選擇正確的處理的方式,才不至於無緣由的浪費處理效能與資源,另外在使用平行處理時,需要先確保處理過程中的每一筆資料沒有前後關係,就算原有資料是有關係的若能事前將資料分類處理最後在用平行處理,都可以盡可能加速資料處理的效能。

在 javascript 中關於 flow control 也是一個重要的議題,用對處理方式將會讓效能從地獄到天堂,一點心得與大家分享。

張貼留言