Node.js based smart shopping cart app

Information

In this page, there is English description followed by Japanese one.
本ページは英語の説明の後に日本語の説明が続きます。

Getting Started

Installing Node.js and npm

You need to have Node.js and npm installed.

To check if you have them installed, open a terminal or command prompt and run the following commands:

node --version
npm --version

If you see an number output similar to x.x.x for each command, then they are both installed and you can continue to the next section.

To install on Windows or mac, you can download the installer from https://nodejs.org/en/download.

To install on Linux, you can use a package manager. Instructions for installing Node.js on your distribution can be found in the following link:
https://nodejs.org/en/download/package-manager

Prerequisite

This example assumes that you've already run the following program that can communicate the decoded result of barcode data with mbed Device Connector:

Import programGR-PEACH_mbed-os-client-ZXingSample

Fork of https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/

Configuring the Applition

In order to run this app, you need to set up the options shown below via .env file stored in the folder GR-PEACH_mbed-os-QRCode-ShoppingCart-node which should be automatically created when cloning this program.

  • ACCESS_KEY
    Set this variable to your Access Key that you can create on mbed Device Connector. if you don't have an Access Key yet, please create it in accordance with the following procedure.
    1. Access https://connector.mbed.com/#accesskeys.
    2. Click CREATE NEW ACCESS KEY.
    /media/uploads/HinoNaka/screenshot7.png
    3. When prompted, enter a name for the access key (e.g. "demo") and click ADD.
    /media/uploads/HinoNaka/screenshot8.png

    After an access key is successfully created, please copy the access key you just created and use it in .env file as follows:

.env

ACCESS_KEY=...
  • PORT
    Set this variable as follows to override the default port for this example if needed. The default port is 8080.

.env

PORT=...

Also, user need to prepare for the comma-delimited list which includes "Item Name" and "Price" which is added to shopping cart, and save it by the name klist.txt as follows:
/media/uploads/HinoNaka/mbed_shoppingcart_fig8.png
The list should be stored in GR-Peach_mbed-os_QRCode_ShoppingCart_node\public\list.

Application Execution

This application consists of 2 tabs. One is Shopping Cart and the other is QR Code Login. In this section, it is described that how those work.

As mentioned above, GR-PEACH_mbed-os-client-ZXingSample should be executed beforehand. For details on how to set up and execute GR-PEACH_mbed-os-client-ZXingSample, please refer to https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/. If the program works properly, you can see the following message in your terminal: /media/uploads/HinoNaka/mbed_shoppingcart_fig4.png

After it is confirmed that the program works properly, please follow the procedure below in order to execute this Web Application.

  • How to invoke this Web Application
    You can now run the application by invoking the following: /media/uploads/HinoNaka/shoppingcart_fig1.png
    Then, you should see the following message if the configuration is successfully done, :
    /media/uploads/HinoNaka/shoppingcart_fig2.png
    Please note that 8080 might be changed. It should depends on your PORT setting mentioned above. If you access the above URL using Web browser, you can see the following Smart Shopping Cart tab by default: /media/uploads/HinoNaka/mbed_shoppingcart_fig3.png

  • How Shopping Cart tab works
    When you decode QR code stored in GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode by GR-PEACH successfully, the item should be added to shopping cart as follows:
    /media/uploads/HinoNaka/mbed_shoppingcart_fig5.png

  • How QR Code Login tab works
    When you choose QR Code Login tab, you can see the following screen indicating it's Locked status.
    /media/uploads/HinoNaka/mbed_shoppingcart_fig6.png
    Then, if you decode the Unlock qrcode described in GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode\qr.pdf, screen should transit to the following one indicating it's Unlocked status.
    /media/uploads/HinoNaka/mbed_shoppingcart_fig7.png
    After that if you you decode the Lock qrcode described in the above qr.pdf, screen should re-transit to Locked status. In this way, the screen transits to Locked and Unlocked status in accordance with the decoded result of QR code.

How to Deploy this app on HEROKU

HEROKU ( https://id.heroku.com ) is PaaS (Platform as a Service) on which Node.js application can deploy free-of charge. By utilizing it, you can access mbed Shopping Cart and QR Code Login from mobile terminal.

Here is the procedure to deploy this application on HEROKU:

  1. Create your HEROKU account at https://signup.heroku.com/login if you haven't created it yet.
  2. Install Heroku Toolbelt
    32-bit: https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-x86.exe
    64-bit: https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-x64.exe )
  3. Launch command prompt (e.g. Windows PowerShell) and move to the project root directory. Then, invoke the command heroku login. At the first time, Email and Password is thought to be required. At that time, please type Email address and password registered at the step 1.
  4. Invoke the command git init
  5. Invoke the command git add . to prepare all the files staged for the next commit
  6. Invoke the command git commit -m "[commit message]" to commit the files staged at the step 5
  7. Invoke the command heroku create. If the command is successfully terminated, the remote repository heroku should be created and associated with the local repository
  8. Invoke the command git push heroku master If the command is successfully terminated, this application should be deployed to HEROKU and its URL should be shown as follows:

remote: -----> Launching...
remote:        Released v3
remote:        https://hogeoge.herokuapp.com/ deployed to Heroku

After all the steps are completed without error, please access the URL http:hogehoge.herokuapp.com/ (i.e URL where https in the URL shown in the step 7 is replaced with http) with Web browser. You should be able to show mbed Shopping Cart on Web browser.

-------------------------------------------------------------------------------------------------------------------------------------------------

Node.jsとnpmのインストール

本アプリケーションを実行するにあたっては、Node.jsとnpmのインストールが必要です。
お使いの開発環境(PC)にNode.js、npmがインストールされているかどうかは、下記コマンドで確認する事ができます。

node --version
npm --version

上記コマンド実行後、x.x.x というバージョン・リビジョン番号が表示されれば、Node.js、npmは既にインストールされていますので、次節以降の手順にしたがってアプリケーションのセットアップを行ってください。未インストールの場合は以降の手順にしたがってNode.js、npmをインストールしてください。

開発環境のホストOSがWindowsまたはmacの場合はhttps://nodejs.org/en/download から入手可能なインストーラを使用してインストールします。

開発環境のホストOSがLinuxの場合は、お使いのディストリビーションに応じたパッケージ管理システムを用いたインストールが可能です。詳細はhttps://nodejs.org/en/download/package-manager を参照ください。

前提条件

本アプリケーションを実行するにあたっては、GR-PEACH上のバーコードデータのデコード結果にmbed Device Connectorからアクセスする下記プログラムを事前にセットアップしておく必要があります。

Import programGR-PEACH_mbed-os-client-ZXingSample

Fork of https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/

アプリケーションの設定

本アプリケーションの実行するためには、.envファイルを介して以下に示すオプションを設定する必要があります。なお、.envファイルはGR-PEACH_mbed-os-QRCode-ShoppingCart-nodeフォルダに格納されています。

  • ACCESS_KEY 本変数にはmbed Device Connector上で生成可能なAccess Keyを設定します。Access Keyが未生成の場合は下記に従って作成してください。
    1. https://connector.mbed.com/#accesskeys にアクセスします。
    2. CREATE NEW ACCESS KEYをクリックします。
    /media/uploads/HinoNaka/screenshot7.png
    3. access keyの名称を入力するように促されたら、任意の名称(例えばdemo等)を入力し、ADDをクリックします。
    /media/uploads/HinoNaka/screenshot8.png

    access keyが正常に生成できたら、コピーして下記のように.envファイルでACCESS_KEYに設定します。

.env

ACCESS_KEY=...
  • PORT 本変数にはWebアプリへのアクセスに使用するポート番号を下記のように設定します。デフォルトのポート番号は 8080 です。8080から変更の必要がなければ、設定は省略可能です。

.env

PORT=...

また、ショッピングカートに追加する品目と値段をカンマ区切りで下記のように記載したリストを準備し、klist.txtという名称でGR-Peach_mbed-os_QRCode_ShoppingCart_node\public\listフォルダに格納してください。

/media/uploads/HinoNaka/mbed_shoppingcart_fig8.png

アプリケーションの実行

本アプリケーションでは、Shopping CartQR Code Loginという2つのタブが実装されています。以下、それぞれの動作方法について記載します。
なお上述の通り、本アプリケーションの実行に際しては、事前にGR-PEACH_mbed-os-client-ZXingSampleを実行しておく必要があります。GR-PEACH_mbed-os-client-ZXingSampleのセットアップ方法、および実行方法に関しては、https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/ を参照ください。プログラムが正常に動作している場合、下記のメッセージがターミナルに表示されます。
/media/uploads/HinoNaka/mbed_shoppingcart_fig4.png

プログラムの正常動作が確認できたら、以降の手順に従ってWebアプリケーションを実行します。

  • Webアプリケーションの起動
    下記コマンドでWebアプリケーションを起動可能です。
    /media/uploads/HinoNaka/shoppingcart_fig1.png
    上述のアプリケーション設定が正常に行われていれば、下記メッセージが表示されます。
    /media/uploads/HinoNaka/shoppingcart_fig2.png
    なお、8080PORT設定に応じた値となります。
    続いて、上述のURLにWebブラウザでアクセスすると、下記のSmart Shopping Cartの画面が表示されます。
    /media/uploads/HinoNaka/mbed_shoppingcart_fig3.png

  • Shopping Cartタブ
    GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode\qrcode.pdf に記載されている Birthday CakeParty CupsBeer KegsPound of beefBuflle-proof vest のQRコードをデコードすると、下記のようにデコードしたアイテムが都度ショッピングカートに追加されます。
    /media/uploads/HinoNaka/mbed_shoppingcart_fig5.png

  • QR Code Loginタブ
    このタブを選択すると、下記のLock状態を示す画面が表示されます。 /media/uploads/HinoNaka/mbed_shoppingcart_fig6.png
    ここで、GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode\qrcode.pdf に記載のUnlock QRコードをデコードすると、Unlock状態を示す下記の画面に遷移します。 /media/uploads/HinoNaka/mbed_shoppingcart_fig7.png

    この後、Lock QRコードをデコードすると画面はLock状態に再度遷移します。

    このようにQR Code Loginタブでは、LockUnlockのQRコードをデコードする都度、対応する画面に遷移するアプリケーションです。

HEROKUへのデプロイ

HEROKU ( https://id.heroku.com) はNode.jsアプリが無償でデプロイ可能なPaaS (Platform as a Service)と呼ばれるサービスです。HEROKUを活用する事で、mbed Shopping CartQR Code Loginにモバイル端末等からアクセスする事が可能となります。

以下、HEROKUへ本アプリをデプロイする手順を説明します。

  1. HEROKUのアカウントを所有していない場合は https://signup.heroku.com/login でアカウントを作成してください
  2. Heroku Toolbeltをインストールします
    32-bit版: https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-x86.exe
    64-bit版: https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-x64.exe )
  3. ターミナルソフトウェア(例えばWindows PowerShell)を立上げます。そして本アプリのルートディレクトリへ移動し、heroku loginコマンドを実行します。Emailアドレスとパスワードの入力を求められた場合は、アカウント生成時に入力したアドレスとパスワードを入力してください。
  4. git initコマンドを実行します
  5. git add .コマンドを実行し、全ファイルをコミット対象に設定します
  6. git commit -m "[commit message]" で、全ファイルをコミットします
  7. heroku createを実行します。本コマンドが正常終了すると、リモートリポジトリ herokuが設定されます
  8. git push heroku master本コマンドが正常終了すると、HEROKUへのデプロイが完了し、下記のように本WebアプリのURLが表示されます

remote: -----> Launching...
remote:        Released v3
remote:        https://hogeoge.herokuapp.com/ deployed to Heroku

上記の全ての手順が完了したら、http:hogehoge.herokuapp.com/ ( 8. で表示されたURL中のhttpshttpに置換えたもの)へブラウザ等でアクセスします。途中でエラーが発生していなければ、mbed Shopping CartがWebブラウザ上に表示されます。

Committer:
Osamu Nakamura
Date:
Fri Jan 12 19:05:14 2018 +0900
Revision:
0:a40b9a259b52
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Osamu Nakamura 0:a40b9a259b52 1 # Async.js
Osamu Nakamura 0:a40b9a259b52 2
Osamu Nakamura 0:a40b9a259b52 3 [![Build Status via Travis CI](https://travis-ci.org/caolan/async.svg?branch=master)](https://travis-ci.org/caolan/async)
Osamu Nakamura 0:a40b9a259b52 4 [![NPM version](http://img.shields.io/npm/v/async.svg)](https://www.npmjs.org/package/async)
Osamu Nakamura 0:a40b9a259b52 5 [![Coverage Status](https://coveralls.io/repos/caolan/async/badge.svg?branch=master)](https://coveralls.io/r/caolan/async?branch=master)
Osamu Nakamura 0:a40b9a259b52 6 [![Join the chat at https://gitter.im/caolan/async](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/caolan/async?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Osamu Nakamura 0:a40b9a259b52 7
Osamu Nakamura 0:a40b9a259b52 8
Osamu Nakamura 0:a40b9a259b52 9 Async is a utility module which provides straight-forward, powerful functions
Osamu Nakamura 0:a40b9a259b52 10 for working with asynchronous JavaScript. Although originally designed for
Osamu Nakamura 0:a40b9a259b52 11 use with [Node.js](http://nodejs.org) and installable via `npm install async`,
Osamu Nakamura 0:a40b9a259b52 12 it can also be used directly in the browser.
Osamu Nakamura 0:a40b9a259b52 13
Osamu Nakamura 0:a40b9a259b52 14 Async is also installable via:
Osamu Nakamura 0:a40b9a259b52 15
Osamu Nakamura 0:a40b9a259b52 16 - [bower](http://bower.io/): `bower install async`
Osamu Nakamura 0:a40b9a259b52 17 - [component](https://github.com/component/component): `component install
Osamu Nakamura 0:a40b9a259b52 18 caolan/async`
Osamu Nakamura 0:a40b9a259b52 19 - [jam](http://jamjs.org/): `jam install async`
Osamu Nakamura 0:a40b9a259b52 20 - [spm](http://spmjs.io/): `spm install async`
Osamu Nakamura 0:a40b9a259b52 21
Osamu Nakamura 0:a40b9a259b52 22 Async provides around 20 functions that include the usual 'functional'
Osamu Nakamura 0:a40b9a259b52 23 suspects (`map`, `reduce`, `filter`, `each`…) as well as some common patterns
Osamu Nakamura 0:a40b9a259b52 24 for asynchronous control flow (`parallel`, `series`, `waterfall`…). All these
Osamu Nakamura 0:a40b9a259b52 25 functions assume you follow the Node.js convention of providing a single
Osamu Nakamura 0:a40b9a259b52 26 callback as the last argument of your `async` function.
Osamu Nakamura 0:a40b9a259b52 27
Osamu Nakamura 0:a40b9a259b52 28
Osamu Nakamura 0:a40b9a259b52 29 ## Quick Examples
Osamu Nakamura 0:a40b9a259b52 30
Osamu Nakamura 0:a40b9a259b52 31 ```javascript
Osamu Nakamura 0:a40b9a259b52 32 async.map(['file1','file2','file3'], fs.stat, function(err, results){
Osamu Nakamura 0:a40b9a259b52 33 // results is now an array of stats for each file
Osamu Nakamura 0:a40b9a259b52 34 });
Osamu Nakamura 0:a40b9a259b52 35
Osamu Nakamura 0:a40b9a259b52 36 async.filter(['file1','file2','file3'], fs.exists, function(results){
Osamu Nakamura 0:a40b9a259b52 37 // results now equals an array of the existing files
Osamu Nakamura 0:a40b9a259b52 38 });
Osamu Nakamura 0:a40b9a259b52 39
Osamu Nakamura 0:a40b9a259b52 40 async.parallel([
Osamu Nakamura 0:a40b9a259b52 41 function(){ ... },
Osamu Nakamura 0:a40b9a259b52 42 function(){ ... }
Osamu Nakamura 0:a40b9a259b52 43 ], callback);
Osamu Nakamura 0:a40b9a259b52 44
Osamu Nakamura 0:a40b9a259b52 45 async.series([
Osamu Nakamura 0:a40b9a259b52 46 function(){ ... },
Osamu Nakamura 0:a40b9a259b52 47 function(){ ... }
Osamu Nakamura 0:a40b9a259b52 48 ]);
Osamu Nakamura 0:a40b9a259b52 49 ```
Osamu Nakamura 0:a40b9a259b52 50
Osamu Nakamura 0:a40b9a259b52 51 There are many more functions available so take a look at the docs below for a
Osamu Nakamura 0:a40b9a259b52 52 full list. This module aims to be comprehensive, so if you feel anything is
Osamu Nakamura 0:a40b9a259b52 53 missing please create a GitHub issue for it.
Osamu Nakamura 0:a40b9a259b52 54
Osamu Nakamura 0:a40b9a259b52 55 ## Common Pitfalls <sub>[(StackOverflow)](http://stackoverflow.com/questions/tagged/async.js)</sub>
Osamu Nakamura 0:a40b9a259b52 56 ### Synchronous iteration functions
Osamu Nakamura 0:a40b9a259b52 57
Osamu Nakamura 0:a40b9a259b52 58 If you get an error like `RangeError: Maximum call stack size exceeded.` or other stack overflow issues when using async, you are likely using a synchronous iterator. By *synchronous* we mean a function that calls its callback on the same tick in the javascript event loop, without doing any I/O or using any timers. Calling many callbacks iteratively will quickly overflow the stack. If you run into this issue, just defer your callback with `async.setImmediate` to start a new call stack on the next tick of the event loop.
Osamu Nakamura 0:a40b9a259b52 59
Osamu Nakamura 0:a40b9a259b52 60 This can also arise by accident if you callback early in certain cases:
Osamu Nakamura 0:a40b9a259b52 61
Osamu Nakamura 0:a40b9a259b52 62 ```js
Osamu Nakamura 0:a40b9a259b52 63 async.eachSeries(hugeArray, function iterator(item, callback) {
Osamu Nakamura 0:a40b9a259b52 64 if (inCache(item)) {
Osamu Nakamura 0:a40b9a259b52 65 callback(null, cache[item]); // if many items are cached, you'll overflow
Osamu Nakamura 0:a40b9a259b52 66 } else {
Osamu Nakamura 0:a40b9a259b52 67 doSomeIO(item, callback);
Osamu Nakamura 0:a40b9a259b52 68 }
Osamu Nakamura 0:a40b9a259b52 69 }, function done() {
Osamu Nakamura 0:a40b9a259b52 70 //...
Osamu Nakamura 0:a40b9a259b52 71 });
Osamu Nakamura 0:a40b9a259b52 72 ```
Osamu Nakamura 0:a40b9a259b52 73
Osamu Nakamura 0:a40b9a259b52 74 Just change it to:
Osamu Nakamura 0:a40b9a259b52 75
Osamu Nakamura 0:a40b9a259b52 76 ```js
Osamu Nakamura 0:a40b9a259b52 77 async.eachSeries(hugeArray, function iterator(item, callback) {
Osamu Nakamura 0:a40b9a259b52 78 if (inCache(item)) {
Osamu Nakamura 0:a40b9a259b52 79 async.setImmediate(function () {
Osamu Nakamura 0:a40b9a259b52 80 callback(null, cache[item]);
Osamu Nakamura 0:a40b9a259b52 81 });
Osamu Nakamura 0:a40b9a259b52 82 } else {
Osamu Nakamura 0:a40b9a259b52 83 doSomeIO(item, callback);
Osamu Nakamura 0:a40b9a259b52 84 //...
Osamu Nakamura 0:a40b9a259b52 85 ```
Osamu Nakamura 0:a40b9a259b52 86
Osamu Nakamura 0:a40b9a259b52 87 Async guards against synchronous functions in some, but not all, cases. If you are still running into stack overflows, you can defer as suggested above, or wrap functions with [`async.ensureAsync`](#ensureAsync) Functions that are asynchronous by their nature do not have this problem and don't need the extra callback deferral.
Osamu Nakamura 0:a40b9a259b52 88
Osamu Nakamura 0:a40b9a259b52 89 If JavaScript's event loop is still a bit nebulous, check out [this article](http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/) or [this talk](http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html) for more detailed information about how it works.
Osamu Nakamura 0:a40b9a259b52 90
Osamu Nakamura 0:a40b9a259b52 91
Osamu Nakamura 0:a40b9a259b52 92 ### Multiple callbacks
Osamu Nakamura 0:a40b9a259b52 93
Osamu Nakamura 0:a40b9a259b52 94 Make sure to always `return` when calling a callback early, otherwise you will cause multiple callbacks and unpredictable behavior in many cases.
Osamu Nakamura 0:a40b9a259b52 95
Osamu Nakamura 0:a40b9a259b52 96 ```js
Osamu Nakamura 0:a40b9a259b52 97 async.waterfall([
Osamu Nakamura 0:a40b9a259b52 98 function (callback) {
Osamu Nakamura 0:a40b9a259b52 99 getSomething(options, function (err, result) {
Osamu Nakamura 0:a40b9a259b52 100 if (err) {
Osamu Nakamura 0:a40b9a259b52 101 callback(new Error("failed getting something:" + err.message));
Osamu Nakamura 0:a40b9a259b52 102 // we should return here
Osamu Nakamura 0:a40b9a259b52 103 }
Osamu Nakamura 0:a40b9a259b52 104 // since we did not return, this callback still will be called and
Osamu Nakamura 0:a40b9a259b52 105 // `processData` will be called twice
Osamu Nakamura 0:a40b9a259b52 106 callback(null, result);
Osamu Nakamura 0:a40b9a259b52 107 });
Osamu Nakamura 0:a40b9a259b52 108 },
Osamu Nakamura 0:a40b9a259b52 109 processData
Osamu Nakamura 0:a40b9a259b52 110 ], done)
Osamu Nakamura 0:a40b9a259b52 111 ```
Osamu Nakamura 0:a40b9a259b52 112
Osamu Nakamura 0:a40b9a259b52 113 It is always good practice to `return callback(err, result)` whenever a callback call is not the last statement of a function.
Osamu Nakamura 0:a40b9a259b52 114
Osamu Nakamura 0:a40b9a259b52 115
Osamu Nakamura 0:a40b9a259b52 116 ### Binding a context to an iterator
Osamu Nakamura 0:a40b9a259b52 117
Osamu Nakamura 0:a40b9a259b52 118 This section is really about `bind`, not about `async`. If you are wondering how to
Osamu Nakamura 0:a40b9a259b52 119 make `async` execute your iterators in a given context, or are confused as to why
Osamu Nakamura 0:a40b9a259b52 120 a method of another library isn't working as an iterator, study this example:
Osamu Nakamura 0:a40b9a259b52 121
Osamu Nakamura 0:a40b9a259b52 122 ```js
Osamu Nakamura 0:a40b9a259b52 123 // Here is a simple object with an (unnecessarily roundabout) squaring method
Osamu Nakamura 0:a40b9a259b52 124 var AsyncSquaringLibrary = {
Osamu Nakamura 0:a40b9a259b52 125 squareExponent: 2,
Osamu Nakamura 0:a40b9a259b52 126 square: function(number, callback){
Osamu Nakamura 0:a40b9a259b52 127 var result = Math.pow(number, this.squareExponent);
Osamu Nakamura 0:a40b9a259b52 128 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 129 callback(null, result);
Osamu Nakamura 0:a40b9a259b52 130 }, 200);
Osamu Nakamura 0:a40b9a259b52 131 }
Osamu Nakamura 0:a40b9a259b52 132 };
Osamu Nakamura 0:a40b9a259b52 133
Osamu Nakamura 0:a40b9a259b52 134 async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){
Osamu Nakamura 0:a40b9a259b52 135 // result is [NaN, NaN, NaN]
Osamu Nakamura 0:a40b9a259b52 136 // This fails because the `this.squareExponent` expression in the square
Osamu Nakamura 0:a40b9a259b52 137 // function is not evaluated in the context of AsyncSquaringLibrary, and is
Osamu Nakamura 0:a40b9a259b52 138 // therefore undefined.
Osamu Nakamura 0:a40b9a259b52 139 });
Osamu Nakamura 0:a40b9a259b52 140
Osamu Nakamura 0:a40b9a259b52 141 async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){
Osamu Nakamura 0:a40b9a259b52 142 // result is [1, 4, 9]
Osamu Nakamura 0:a40b9a259b52 143 // With the help of bind we can attach a context to the iterator before
Osamu Nakamura 0:a40b9a259b52 144 // passing it to async. Now the square function will be executed in its
Osamu Nakamura 0:a40b9a259b52 145 // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`
Osamu Nakamura 0:a40b9a259b52 146 // will be as expected.
Osamu Nakamura 0:a40b9a259b52 147 });
Osamu Nakamura 0:a40b9a259b52 148 ```
Osamu Nakamura 0:a40b9a259b52 149
Osamu Nakamura 0:a40b9a259b52 150 ## Download
Osamu Nakamura 0:a40b9a259b52 151
Osamu Nakamura 0:a40b9a259b52 152 The source is available for download from
Osamu Nakamura 0:a40b9a259b52 153 [GitHub](https://github.com/caolan/async/blob/master/lib/async.js).
Osamu Nakamura 0:a40b9a259b52 154 Alternatively, you can install using Node Package Manager (`npm`):
Osamu Nakamura 0:a40b9a259b52 155
Osamu Nakamura 0:a40b9a259b52 156 npm install async
Osamu Nakamura 0:a40b9a259b52 157
Osamu Nakamura 0:a40b9a259b52 158 As well as using Bower:
Osamu Nakamura 0:a40b9a259b52 159
Osamu Nakamura 0:a40b9a259b52 160 bower install async
Osamu Nakamura 0:a40b9a259b52 161
Osamu Nakamura 0:a40b9a259b52 162 __Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed
Osamu Nakamura 0:a40b9a259b52 163
Osamu Nakamura 0:a40b9a259b52 164 ## In the Browser
Osamu Nakamura 0:a40b9a259b52 165
Osamu Nakamura 0:a40b9a259b52 166 So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5.
Osamu Nakamura 0:a40b9a259b52 167
Osamu Nakamura 0:a40b9a259b52 168 Usage:
Osamu Nakamura 0:a40b9a259b52 169
Osamu Nakamura 0:a40b9a259b52 170 ```html
Osamu Nakamura 0:a40b9a259b52 171 <script type="text/javascript" src="async.js"></script>
Osamu Nakamura 0:a40b9a259b52 172 <script type="text/javascript">
Osamu Nakamura 0:a40b9a259b52 173
Osamu Nakamura 0:a40b9a259b52 174 async.map(data, asyncProcess, function(err, results){
Osamu Nakamura 0:a40b9a259b52 175 alert(results);
Osamu Nakamura 0:a40b9a259b52 176 });
Osamu Nakamura 0:a40b9a259b52 177
Osamu Nakamura 0:a40b9a259b52 178 </script>
Osamu Nakamura 0:a40b9a259b52 179 ```
Osamu Nakamura 0:a40b9a259b52 180
Osamu Nakamura 0:a40b9a259b52 181 ## Documentation
Osamu Nakamura 0:a40b9a259b52 182
Osamu Nakamura 0:a40b9a259b52 183 Some functions are also available in the following forms:
Osamu Nakamura 0:a40b9a259b52 184 * `<name>Series` - the same as `<name>` but runs only a single async operation at a time
Osamu Nakamura 0:a40b9a259b52 185 * `<name>Limit` - the same as `<name>` but runs a maximum of `limit` async operations at a time
Osamu Nakamura 0:a40b9a259b52 186
Osamu Nakamura 0:a40b9a259b52 187 ### Collections
Osamu Nakamura 0:a40b9a259b52 188
Osamu Nakamura 0:a40b9a259b52 189 * [`each`](#each), `eachSeries`, `eachLimit`
Osamu Nakamura 0:a40b9a259b52 190 * [`forEachOf`](#forEachOf), `forEachOfSeries`, `forEachOfLimit`
Osamu Nakamura 0:a40b9a259b52 191 * [`map`](#map), `mapSeries`, `mapLimit`
Osamu Nakamura 0:a40b9a259b52 192 * [`filter`](#filter), `filterSeries`, `filterLimit`
Osamu Nakamura 0:a40b9a259b52 193 * [`reject`](#reject), `rejectSeries`, `rejectLimit`
Osamu Nakamura 0:a40b9a259b52 194 * [`reduce`](#reduce), [`reduceRight`](#reduceRight)
Osamu Nakamura 0:a40b9a259b52 195 * [`detect`](#detect), `detectSeries`, `detectLimit`
Osamu Nakamura 0:a40b9a259b52 196 * [`sortBy`](#sortBy)
Osamu Nakamura 0:a40b9a259b52 197 * [`some`](#some), `someLimit`
Osamu Nakamura 0:a40b9a259b52 198 * [`every`](#every), `everyLimit`
Osamu Nakamura 0:a40b9a259b52 199 * [`concat`](#concat), `concatSeries`
Osamu Nakamura 0:a40b9a259b52 200
Osamu Nakamura 0:a40b9a259b52 201 ### Control Flow
Osamu Nakamura 0:a40b9a259b52 202
Osamu Nakamura 0:a40b9a259b52 203 * [`series`](#seriestasks-callback)
Osamu Nakamura 0:a40b9a259b52 204 * [`parallel`](#parallel), `parallelLimit`
Osamu Nakamura 0:a40b9a259b52 205 * [`whilst`](#whilst), [`doWhilst`](#doWhilst)
Osamu Nakamura 0:a40b9a259b52 206 * [`until`](#until), [`doUntil`](#doUntil)
Osamu Nakamura 0:a40b9a259b52 207 * [`during`](#during), [`doDuring`](#doDuring)
Osamu Nakamura 0:a40b9a259b52 208 * [`forever`](#forever)
Osamu Nakamura 0:a40b9a259b52 209 * [`waterfall`](#waterfall)
Osamu Nakamura 0:a40b9a259b52 210 * [`compose`](#compose)
Osamu Nakamura 0:a40b9a259b52 211 * [`seq`](#seq)
Osamu Nakamura 0:a40b9a259b52 212 * [`applyEach`](#applyEach), `applyEachSeries`
Osamu Nakamura 0:a40b9a259b52 213 * [`queue`](#queue), [`priorityQueue`](#priorityQueue)
Osamu Nakamura 0:a40b9a259b52 214 * [`cargo`](#cargo)
Osamu Nakamura 0:a40b9a259b52 215 * [`auto`](#auto)
Osamu Nakamura 0:a40b9a259b52 216 * [`retry`](#retry)
Osamu Nakamura 0:a40b9a259b52 217 * [`iterator`](#iterator)
Osamu Nakamura 0:a40b9a259b52 218 * [`times`](#times), `timesSeries`, `timesLimit`
Osamu Nakamura 0:a40b9a259b52 219
Osamu Nakamura 0:a40b9a259b52 220 ### Utils
Osamu Nakamura 0:a40b9a259b52 221
Osamu Nakamura 0:a40b9a259b52 222 * [`apply`](#apply)
Osamu Nakamura 0:a40b9a259b52 223 * [`nextTick`](#nextTick)
Osamu Nakamura 0:a40b9a259b52 224 * [`memoize`](#memoize)
Osamu Nakamura 0:a40b9a259b52 225 * [`unmemoize`](#unmemoize)
Osamu Nakamura 0:a40b9a259b52 226 * [`ensureAsync`](#ensureAsync)
Osamu Nakamura 0:a40b9a259b52 227 * [`constant`](#constant)
Osamu Nakamura 0:a40b9a259b52 228 * [`asyncify`](#asyncify)
Osamu Nakamura 0:a40b9a259b52 229 * [`wrapSync`](#wrapSync)
Osamu Nakamura 0:a40b9a259b52 230 * [`log`](#log)
Osamu Nakamura 0:a40b9a259b52 231 * [`dir`](#dir)
Osamu Nakamura 0:a40b9a259b52 232 * [`noConflict`](#noConflict)
Osamu Nakamura 0:a40b9a259b52 233
Osamu Nakamura 0:a40b9a259b52 234 ## Collections
Osamu Nakamura 0:a40b9a259b52 235
Osamu Nakamura 0:a40b9a259b52 236 <a name="forEach" />
Osamu Nakamura 0:a40b9a259b52 237 <a name="each" />
Osamu Nakamura 0:a40b9a259b52 238 ### each(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 239
Osamu Nakamura 0:a40b9a259b52 240 Applies the function `iterator` to each item in `arr`, in parallel.
Osamu Nakamura 0:a40b9a259b52 241 The `iterator` is called with an item from the list, and a callback for when it
Osamu Nakamura 0:a40b9a259b52 242 has finished. If the `iterator` passes an error to its `callback`, the main
Osamu Nakamura 0:a40b9a259b52 243 `callback` (for the `each` function) is immediately called with the error.
Osamu Nakamura 0:a40b9a259b52 244
Osamu Nakamura 0:a40b9a259b52 245 Note, that since this function applies `iterator` to each item in parallel,
Osamu Nakamura 0:a40b9a259b52 246 there is no guarantee that the iterator functions will complete in order.
Osamu Nakamura 0:a40b9a259b52 247
Osamu Nakamura 0:a40b9a259b52 248 __Arguments__
Osamu Nakamura 0:a40b9a259b52 249
Osamu Nakamura 0:a40b9a259b52 250 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 251 * `iterator(item, callback)` - A function to apply to each item in `arr`.
Osamu Nakamura 0:a40b9a259b52 252 The iterator is passed a `callback(err)` which must be called once it has
Osamu Nakamura 0:a40b9a259b52 253 completed. If no error has occurred, the `callback` should be run without
Osamu Nakamura 0:a40b9a259b52 254 arguments or with an explicit `null` argument. The array index is not passed
Osamu Nakamura 0:a40b9a259b52 255 to the iterator. If you need the index, use [`forEachOf`](#forEachOf).
Osamu Nakamura 0:a40b9a259b52 256 * `callback(err)` - *Optional* A callback which is called when all `iterator` functions
Osamu Nakamura 0:a40b9a259b52 257 have finished, or an error occurs.
Osamu Nakamura 0:a40b9a259b52 258
Osamu Nakamura 0:a40b9a259b52 259 __Examples__
Osamu Nakamura 0:a40b9a259b52 260
Osamu Nakamura 0:a40b9a259b52 261
Osamu Nakamura 0:a40b9a259b52 262 ```js
Osamu Nakamura 0:a40b9a259b52 263 // assuming openFiles is an array of file names and saveFile is a function
Osamu Nakamura 0:a40b9a259b52 264 // to save the modified contents of that file:
Osamu Nakamura 0:a40b9a259b52 265
Osamu Nakamura 0:a40b9a259b52 266 async.each(openFiles, saveFile, function(err){
Osamu Nakamura 0:a40b9a259b52 267 // if any of the saves produced an error, err would equal that error
Osamu Nakamura 0:a40b9a259b52 268 });
Osamu Nakamura 0:a40b9a259b52 269 ```
Osamu Nakamura 0:a40b9a259b52 270
Osamu Nakamura 0:a40b9a259b52 271 ```js
Osamu Nakamura 0:a40b9a259b52 272 // assuming openFiles is an array of file names
Osamu Nakamura 0:a40b9a259b52 273
Osamu Nakamura 0:a40b9a259b52 274 async.each(openFiles, function(file, callback) {
Osamu Nakamura 0:a40b9a259b52 275
Osamu Nakamura 0:a40b9a259b52 276 // Perform operation on file here.
Osamu Nakamura 0:a40b9a259b52 277 console.log('Processing file ' + file);
Osamu Nakamura 0:a40b9a259b52 278
Osamu Nakamura 0:a40b9a259b52 279 if( file.length > 32 ) {
Osamu Nakamura 0:a40b9a259b52 280 console.log('This file name is too long');
Osamu Nakamura 0:a40b9a259b52 281 callback('File name too long');
Osamu Nakamura 0:a40b9a259b52 282 } else {
Osamu Nakamura 0:a40b9a259b52 283 // Do work to process file here
Osamu Nakamura 0:a40b9a259b52 284 console.log('File processed');
Osamu Nakamura 0:a40b9a259b52 285 callback();
Osamu Nakamura 0:a40b9a259b52 286 }
Osamu Nakamura 0:a40b9a259b52 287 }, function(err){
Osamu Nakamura 0:a40b9a259b52 288 // if any of the file processing produced an error, err would equal that error
Osamu Nakamura 0:a40b9a259b52 289 if( err ) {
Osamu Nakamura 0:a40b9a259b52 290 // One of the iterations produced an error.
Osamu Nakamura 0:a40b9a259b52 291 // All processing will now stop.
Osamu Nakamura 0:a40b9a259b52 292 console.log('A file failed to process');
Osamu Nakamura 0:a40b9a259b52 293 } else {
Osamu Nakamura 0:a40b9a259b52 294 console.log('All files have been processed successfully');
Osamu Nakamura 0:a40b9a259b52 295 }
Osamu Nakamura 0:a40b9a259b52 296 });
Osamu Nakamura 0:a40b9a259b52 297 ```
Osamu Nakamura 0:a40b9a259b52 298
Osamu Nakamura 0:a40b9a259b52 299 __Related__
Osamu Nakamura 0:a40b9a259b52 300
Osamu Nakamura 0:a40b9a259b52 301 * eachSeries(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 302 * eachLimit(arr, limit, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 303
Osamu Nakamura 0:a40b9a259b52 304 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 305
Osamu Nakamura 0:a40b9a259b52 306 <a name="forEachOf" />
Osamu Nakamura 0:a40b9a259b52 307 <a name="eachOf" />
Osamu Nakamura 0:a40b9a259b52 308
Osamu Nakamura 0:a40b9a259b52 309 ### forEachOf(obj, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 310
Osamu Nakamura 0:a40b9a259b52 311 Like `each`, except that it iterates over objects, and passes the key as the second argument to the iterator.
Osamu Nakamura 0:a40b9a259b52 312
Osamu Nakamura 0:a40b9a259b52 313 __Arguments__
Osamu Nakamura 0:a40b9a259b52 314
Osamu Nakamura 0:a40b9a259b52 315 * `obj` - An object or array to iterate over.
Osamu Nakamura 0:a40b9a259b52 316 * `iterator(item, key, callback)` - A function to apply to each item in `obj`.
Osamu Nakamura 0:a40b9a259b52 317 The `key` is the item's key, or index in the case of an array. The iterator is
Osamu Nakamura 0:a40b9a259b52 318 passed a `callback(err)` which must be called once it has completed. If no
Osamu Nakamura 0:a40b9a259b52 319 error has occurred, the callback should be run without arguments or with an
Osamu Nakamura 0:a40b9a259b52 320 explicit `null` argument.
Osamu Nakamura 0:a40b9a259b52 321 * `callback(err)` - *Optional* A callback which is called when all `iterator` functions have finished, or an error occurs.
Osamu Nakamura 0:a40b9a259b52 322
Osamu Nakamura 0:a40b9a259b52 323 __Example__
Osamu Nakamura 0:a40b9a259b52 324
Osamu Nakamura 0:a40b9a259b52 325 ```js
Osamu Nakamura 0:a40b9a259b52 326 var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"};
Osamu Nakamura 0:a40b9a259b52 327 var configs = {};
Osamu Nakamura 0:a40b9a259b52 328
Osamu Nakamura 0:a40b9a259b52 329 async.forEachOf(obj, function (value, key, callback) {
Osamu Nakamura 0:a40b9a259b52 330 fs.readFile(__dirname + value, "utf8", function (err, data) {
Osamu Nakamura 0:a40b9a259b52 331 if (err) return callback(err);
Osamu Nakamura 0:a40b9a259b52 332 try {
Osamu Nakamura 0:a40b9a259b52 333 configs[key] = JSON.parse(data);
Osamu Nakamura 0:a40b9a259b52 334 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 335 return callback(e);
Osamu Nakamura 0:a40b9a259b52 336 }
Osamu Nakamura 0:a40b9a259b52 337 callback();
Osamu Nakamura 0:a40b9a259b52 338 })
Osamu Nakamura 0:a40b9a259b52 339 }, function (err) {
Osamu Nakamura 0:a40b9a259b52 340 if (err) console.error(err.message);
Osamu Nakamura 0:a40b9a259b52 341 // configs is now a map of JSON data
Osamu Nakamura 0:a40b9a259b52 342 doSomethingWith(configs);
Osamu Nakamura 0:a40b9a259b52 343 })
Osamu Nakamura 0:a40b9a259b52 344 ```
Osamu Nakamura 0:a40b9a259b52 345
Osamu Nakamura 0:a40b9a259b52 346 __Related__
Osamu Nakamura 0:a40b9a259b52 347
Osamu Nakamura 0:a40b9a259b52 348 * forEachOfSeries(obj, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 349 * forEachOfLimit(obj, limit, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 350
Osamu Nakamura 0:a40b9a259b52 351 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 352
Osamu Nakamura 0:a40b9a259b52 353 <a name="map" />
Osamu Nakamura 0:a40b9a259b52 354 ### map(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 355
Osamu Nakamura 0:a40b9a259b52 356 Produces a new array of values by mapping each value in `arr` through
Osamu Nakamura 0:a40b9a259b52 357 the `iterator` function. The `iterator` is called with an item from `arr` and a
Osamu Nakamura 0:a40b9a259b52 358 callback for when it has finished processing. Each of these callback takes 2 arguments:
Osamu Nakamura 0:a40b9a259b52 359 an `error`, and the transformed item from `arr`. If `iterator` passes an error to its
Osamu Nakamura 0:a40b9a259b52 360 callback, the main `callback` (for the `map` function) is immediately called with the error.
Osamu Nakamura 0:a40b9a259b52 361
Osamu Nakamura 0:a40b9a259b52 362 Note, that since this function applies the `iterator` to each item in parallel,
Osamu Nakamura 0:a40b9a259b52 363 there is no guarantee that the `iterator` functions will complete in order.
Osamu Nakamura 0:a40b9a259b52 364 However, the results array will be in the same order as the original `arr`.
Osamu Nakamura 0:a40b9a259b52 365
Osamu Nakamura 0:a40b9a259b52 366 __Arguments__
Osamu Nakamura 0:a40b9a259b52 367
Osamu Nakamura 0:a40b9a259b52 368 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 369 * `iterator(item, callback)` - A function to apply to each item in `arr`.
Osamu Nakamura 0:a40b9a259b52 370 The iterator is passed a `callback(err, transformed)` which must be called once
Osamu Nakamura 0:a40b9a259b52 371 it has completed with an error (which can be `null`) and a transformed item.
Osamu Nakamura 0:a40b9a259b52 372 * `callback(err, results)` - *Optional* A callback which is called when all `iterator`
Osamu Nakamura 0:a40b9a259b52 373 functions have finished, or an error occurs. Results is an array of the
Osamu Nakamura 0:a40b9a259b52 374 transformed items from the `arr`.
Osamu Nakamura 0:a40b9a259b52 375
Osamu Nakamura 0:a40b9a259b52 376 __Example__
Osamu Nakamura 0:a40b9a259b52 377
Osamu Nakamura 0:a40b9a259b52 378 ```js
Osamu Nakamura 0:a40b9a259b52 379 async.map(['file1','file2','file3'], fs.stat, function(err, results){
Osamu Nakamura 0:a40b9a259b52 380 // results is now an array of stats for each file
Osamu Nakamura 0:a40b9a259b52 381 });
Osamu Nakamura 0:a40b9a259b52 382 ```
Osamu Nakamura 0:a40b9a259b52 383
Osamu Nakamura 0:a40b9a259b52 384 __Related__
Osamu Nakamura 0:a40b9a259b52 385 * mapSeries(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 386 * mapLimit(arr, limit, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 387
Osamu Nakamura 0:a40b9a259b52 388 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 389
Osamu Nakamura 0:a40b9a259b52 390 <a name="select" />
Osamu Nakamura 0:a40b9a259b52 391 <a name="filter" />
Osamu Nakamura 0:a40b9a259b52 392 ### filter(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 393
Osamu Nakamura 0:a40b9a259b52 394 __Alias:__ `select`
Osamu Nakamura 0:a40b9a259b52 395
Osamu Nakamura 0:a40b9a259b52 396 Returns a new array of all the values in `arr` which pass an async truth test.
Osamu Nakamura 0:a40b9a259b52 397 _The callback for each `iterator` call only accepts a single argument of `true` or
Osamu Nakamura 0:a40b9a259b52 398 `false`; it does not accept an error argument first!_ This is in-line with the
Osamu Nakamura 0:a40b9a259b52 399 way node libraries work with truth tests like `fs.exists`. This operation is
Osamu Nakamura 0:a40b9a259b52 400 performed in parallel, but the results array will be in the same order as the
Osamu Nakamura 0:a40b9a259b52 401 original.
Osamu Nakamura 0:a40b9a259b52 402
Osamu Nakamura 0:a40b9a259b52 403 __Arguments__
Osamu Nakamura 0:a40b9a259b52 404
Osamu Nakamura 0:a40b9a259b52 405 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 406 * `iterator(item, callback)` - A truth test to apply to each item in `arr`.
Osamu Nakamura 0:a40b9a259b52 407 The `iterator` is passed a `callback(truthValue)`, which must be called with a
Osamu Nakamura 0:a40b9a259b52 408 boolean argument once it has completed.
Osamu Nakamura 0:a40b9a259b52 409 * `callback(results)` - *Optional* A callback which is called after all the `iterator`
Osamu Nakamura 0:a40b9a259b52 410 functions have finished.
Osamu Nakamura 0:a40b9a259b52 411
Osamu Nakamura 0:a40b9a259b52 412 __Example__
Osamu Nakamura 0:a40b9a259b52 413
Osamu Nakamura 0:a40b9a259b52 414 ```js
Osamu Nakamura 0:a40b9a259b52 415 async.filter(['file1','file2','file3'], fs.exists, function(results){
Osamu Nakamura 0:a40b9a259b52 416 // results now equals an array of the existing files
Osamu Nakamura 0:a40b9a259b52 417 });
Osamu Nakamura 0:a40b9a259b52 418 ```
Osamu Nakamura 0:a40b9a259b52 419
Osamu Nakamura 0:a40b9a259b52 420 __Related__
Osamu Nakamura 0:a40b9a259b52 421
Osamu Nakamura 0:a40b9a259b52 422 * filterSeries(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 423 * filterLimit(arr, limit, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 424
Osamu Nakamura 0:a40b9a259b52 425 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 426
Osamu Nakamura 0:a40b9a259b52 427 <a name="reject" />
Osamu Nakamura 0:a40b9a259b52 428 ### reject(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 429
Osamu Nakamura 0:a40b9a259b52 430 The opposite of [`filter`](#filter). Removes values that pass an `async` truth test.
Osamu Nakamura 0:a40b9a259b52 431
Osamu Nakamura 0:a40b9a259b52 432 __Related__
Osamu Nakamura 0:a40b9a259b52 433
Osamu Nakamura 0:a40b9a259b52 434 * rejectSeries(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 435 * rejectLimit(arr, limit, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 436
Osamu Nakamura 0:a40b9a259b52 437 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 438
Osamu Nakamura 0:a40b9a259b52 439 <a name="reduce" />
Osamu Nakamura 0:a40b9a259b52 440 ### reduce(arr, memo, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 441
Osamu Nakamura 0:a40b9a259b52 442 __Aliases:__ `inject`, `foldl`
Osamu Nakamura 0:a40b9a259b52 443
Osamu Nakamura 0:a40b9a259b52 444 Reduces `arr` into a single value using an async `iterator` to return
Osamu Nakamura 0:a40b9a259b52 445 each successive step. `memo` is the initial state of the reduction.
Osamu Nakamura 0:a40b9a259b52 446 This function only operates in series.
Osamu Nakamura 0:a40b9a259b52 447
Osamu Nakamura 0:a40b9a259b52 448 For performance reasons, it may make sense to split a call to this function into
Osamu Nakamura 0:a40b9a259b52 449 a parallel map, and then use the normal `Array.prototype.reduce` on the results.
Osamu Nakamura 0:a40b9a259b52 450 This function is for situations where each step in the reduction needs to be async;
Osamu Nakamura 0:a40b9a259b52 451 if you can get the data before reducing it, then it's probably a good idea to do so.
Osamu Nakamura 0:a40b9a259b52 452
Osamu Nakamura 0:a40b9a259b52 453 __Arguments__
Osamu Nakamura 0:a40b9a259b52 454
Osamu Nakamura 0:a40b9a259b52 455 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 456 * `memo` - The initial state of the reduction.
Osamu Nakamura 0:a40b9a259b52 457 * `iterator(memo, item, callback)` - A function applied to each item in the
Osamu Nakamura 0:a40b9a259b52 458 array to produce the next step in the reduction. The `iterator` is passed a
Osamu Nakamura 0:a40b9a259b52 459 `callback(err, reduction)` which accepts an optional error as its first
Osamu Nakamura 0:a40b9a259b52 460 argument, and the state of the reduction as the second. If an error is
Osamu Nakamura 0:a40b9a259b52 461 passed to the callback, the reduction is stopped and the main `callback` is
Osamu Nakamura 0:a40b9a259b52 462 immediately called with the error.
Osamu Nakamura 0:a40b9a259b52 463 * `callback(err, result)` - *Optional* A callback which is called after all the `iterator`
Osamu Nakamura 0:a40b9a259b52 464 functions have finished. Result is the reduced value.
Osamu Nakamura 0:a40b9a259b52 465
Osamu Nakamura 0:a40b9a259b52 466 __Example__
Osamu Nakamura 0:a40b9a259b52 467
Osamu Nakamura 0:a40b9a259b52 468 ```js
Osamu Nakamura 0:a40b9a259b52 469 async.reduce([1,2,3], 0, function(memo, item, callback){
Osamu Nakamura 0:a40b9a259b52 470 // pointless async:
Osamu Nakamura 0:a40b9a259b52 471 process.nextTick(function(){
Osamu Nakamura 0:a40b9a259b52 472 callback(null, memo + item)
Osamu Nakamura 0:a40b9a259b52 473 });
Osamu Nakamura 0:a40b9a259b52 474 }, function(err, result){
Osamu Nakamura 0:a40b9a259b52 475 // result is now equal to the last value of memo, which is 6
Osamu Nakamura 0:a40b9a259b52 476 });
Osamu Nakamura 0:a40b9a259b52 477 ```
Osamu Nakamura 0:a40b9a259b52 478
Osamu Nakamura 0:a40b9a259b52 479 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 480
Osamu Nakamura 0:a40b9a259b52 481 <a name="reduceRight" />
Osamu Nakamura 0:a40b9a259b52 482 ### reduceRight(arr, memo, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 483
Osamu Nakamura 0:a40b9a259b52 484 __Alias:__ `foldr`
Osamu Nakamura 0:a40b9a259b52 485
Osamu Nakamura 0:a40b9a259b52 486 Same as [`reduce`](#reduce), only operates on `arr` in reverse order.
Osamu Nakamura 0:a40b9a259b52 487
Osamu Nakamura 0:a40b9a259b52 488
Osamu Nakamura 0:a40b9a259b52 489 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 490
Osamu Nakamura 0:a40b9a259b52 491 <a name="detect" />
Osamu Nakamura 0:a40b9a259b52 492 ### detect(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 493
Osamu Nakamura 0:a40b9a259b52 494 Returns the first value in `arr` that passes an async truth test. The
Osamu Nakamura 0:a40b9a259b52 495 `iterator` is applied in parallel, meaning the first iterator to return `true` will
Osamu Nakamura 0:a40b9a259b52 496 fire the detect `callback` with that result. That means the result might not be
Osamu Nakamura 0:a40b9a259b52 497 the first item in the original `arr` (in terms of order) that passes the test.
Osamu Nakamura 0:a40b9a259b52 498
Osamu Nakamura 0:a40b9a259b52 499 If order within the original `arr` is important, then look at [`detectSeries`](#detectSeries).
Osamu Nakamura 0:a40b9a259b52 500
Osamu Nakamura 0:a40b9a259b52 501 __Arguments__
Osamu Nakamura 0:a40b9a259b52 502
Osamu Nakamura 0:a40b9a259b52 503 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 504 * `iterator(item, callback)` - A truth test to apply to each item in `arr`.
Osamu Nakamura 0:a40b9a259b52 505 The iterator is passed a `callback(truthValue)` which must be called with a
Osamu Nakamura 0:a40b9a259b52 506 boolean argument once it has completed. **Note: this callback does not take an error as its first argument.**
Osamu Nakamura 0:a40b9a259b52 507 * `callback(result)` - *Optional* A callback which is called as soon as any iterator returns
Osamu Nakamura 0:a40b9a259b52 508 `true`, or after all the `iterator` functions have finished. Result will be
Osamu Nakamura 0:a40b9a259b52 509 the first item in the array that passes the truth test (iterator) or the
Osamu Nakamura 0:a40b9a259b52 510 value `undefined` if none passed. **Note: this callback does not take an error as its first argument.**
Osamu Nakamura 0:a40b9a259b52 511
Osamu Nakamura 0:a40b9a259b52 512 __Example__
Osamu Nakamura 0:a40b9a259b52 513
Osamu Nakamura 0:a40b9a259b52 514 ```js
Osamu Nakamura 0:a40b9a259b52 515 async.detect(['file1','file2','file3'], fs.exists, function(result){
Osamu Nakamura 0:a40b9a259b52 516 // result now equals the first file in the list that exists
Osamu Nakamura 0:a40b9a259b52 517 });
Osamu Nakamura 0:a40b9a259b52 518 ```
Osamu Nakamura 0:a40b9a259b52 519
Osamu Nakamura 0:a40b9a259b52 520 __Related__
Osamu Nakamura 0:a40b9a259b52 521
Osamu Nakamura 0:a40b9a259b52 522 * detectSeries(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 523 * detectLimit(arr, limit, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 524
Osamu Nakamura 0:a40b9a259b52 525 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 526
Osamu Nakamura 0:a40b9a259b52 527 <a name="sortBy" />
Osamu Nakamura 0:a40b9a259b52 528 ### sortBy(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 529
Osamu Nakamura 0:a40b9a259b52 530 Sorts a list by the results of running each `arr` value through an async `iterator`.
Osamu Nakamura 0:a40b9a259b52 531
Osamu Nakamura 0:a40b9a259b52 532 __Arguments__
Osamu Nakamura 0:a40b9a259b52 533
Osamu Nakamura 0:a40b9a259b52 534 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 535 * `iterator(item, callback)` - A function to apply to each item in `arr`.
Osamu Nakamura 0:a40b9a259b52 536 The iterator is passed a `callback(err, sortValue)` which must be called once it
Osamu Nakamura 0:a40b9a259b52 537 has completed with an error (which can be `null`) and a value to use as the sort
Osamu Nakamura 0:a40b9a259b52 538 criteria.
Osamu Nakamura 0:a40b9a259b52 539 * `callback(err, results)` - *Optional* A callback which is called after all the `iterator`
Osamu Nakamura 0:a40b9a259b52 540 functions have finished, or an error occurs. Results is the items from
Osamu Nakamura 0:a40b9a259b52 541 the original `arr` sorted by the values returned by the `iterator` calls.
Osamu Nakamura 0:a40b9a259b52 542
Osamu Nakamura 0:a40b9a259b52 543 __Example__
Osamu Nakamura 0:a40b9a259b52 544
Osamu Nakamura 0:a40b9a259b52 545 ```js
Osamu Nakamura 0:a40b9a259b52 546 async.sortBy(['file1','file2','file3'], function(file, callback){
Osamu Nakamura 0:a40b9a259b52 547 fs.stat(file, function(err, stats){
Osamu Nakamura 0:a40b9a259b52 548 callback(err, stats.mtime);
Osamu Nakamura 0:a40b9a259b52 549 });
Osamu Nakamura 0:a40b9a259b52 550 }, function(err, results){
Osamu Nakamura 0:a40b9a259b52 551 // results is now the original array of files sorted by
Osamu Nakamura 0:a40b9a259b52 552 // modified date
Osamu Nakamura 0:a40b9a259b52 553 });
Osamu Nakamura 0:a40b9a259b52 554 ```
Osamu Nakamura 0:a40b9a259b52 555
Osamu Nakamura 0:a40b9a259b52 556 __Sort Order__
Osamu Nakamura 0:a40b9a259b52 557
Osamu Nakamura 0:a40b9a259b52 558 By modifying the callback parameter the sorting order can be influenced:
Osamu Nakamura 0:a40b9a259b52 559
Osamu Nakamura 0:a40b9a259b52 560 ```js
Osamu Nakamura 0:a40b9a259b52 561 //ascending order
Osamu Nakamura 0:a40b9a259b52 562 async.sortBy([1,9,3,5], function(x, callback){
Osamu Nakamura 0:a40b9a259b52 563 callback(null, x);
Osamu Nakamura 0:a40b9a259b52 564 }, function(err,result){
Osamu Nakamura 0:a40b9a259b52 565 //result callback
Osamu Nakamura 0:a40b9a259b52 566 } );
Osamu Nakamura 0:a40b9a259b52 567
Osamu Nakamura 0:a40b9a259b52 568 //descending order
Osamu Nakamura 0:a40b9a259b52 569 async.sortBy([1,9,3,5], function(x, callback){
Osamu Nakamura 0:a40b9a259b52 570 callback(null, x*-1); //<- x*-1 instead of x, turns the order around
Osamu Nakamura 0:a40b9a259b52 571 }, function(err,result){
Osamu Nakamura 0:a40b9a259b52 572 //result callback
Osamu Nakamura 0:a40b9a259b52 573 } );
Osamu Nakamura 0:a40b9a259b52 574 ```
Osamu Nakamura 0:a40b9a259b52 575
Osamu Nakamura 0:a40b9a259b52 576 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 577
Osamu Nakamura 0:a40b9a259b52 578 <a name="some" />
Osamu Nakamura 0:a40b9a259b52 579 ### some(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 580
Osamu Nakamura 0:a40b9a259b52 581 __Alias:__ `any`
Osamu Nakamura 0:a40b9a259b52 582
Osamu Nakamura 0:a40b9a259b52 583 Returns `true` if at least one element in the `arr` satisfies an async test.
Osamu Nakamura 0:a40b9a259b52 584 _The callback for each iterator call only accepts a single argument of `true` or
Osamu Nakamura 0:a40b9a259b52 585 `false`; it does not accept an error argument first!_ This is in-line with the
Osamu Nakamura 0:a40b9a259b52 586 way node libraries work with truth tests like `fs.exists`. Once any iterator
Osamu Nakamura 0:a40b9a259b52 587 call returns `true`, the main `callback` is immediately called.
Osamu Nakamura 0:a40b9a259b52 588
Osamu Nakamura 0:a40b9a259b52 589 __Arguments__
Osamu Nakamura 0:a40b9a259b52 590
Osamu Nakamura 0:a40b9a259b52 591 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 592 * `iterator(item, callback)` - A truth test to apply to each item in the array
Osamu Nakamura 0:a40b9a259b52 593 in parallel. The iterator is passed a `callback(truthValue)`` which must be
Osamu Nakamura 0:a40b9a259b52 594 called with a boolean argument once it has completed.
Osamu Nakamura 0:a40b9a259b52 595 * `callback(result)` - *Optional* A callback which is called as soon as any iterator returns
Osamu Nakamura 0:a40b9a259b52 596 `true`, or after all the iterator functions have finished. Result will be
Osamu Nakamura 0:a40b9a259b52 597 either `true` or `false` depending on the values of the async tests.
Osamu Nakamura 0:a40b9a259b52 598
Osamu Nakamura 0:a40b9a259b52 599 **Note: the callbacks do not take an error as their first argument.**
Osamu Nakamura 0:a40b9a259b52 600 __Example__
Osamu Nakamura 0:a40b9a259b52 601
Osamu Nakamura 0:a40b9a259b52 602 ```js
Osamu Nakamura 0:a40b9a259b52 603 async.some(['file1','file2','file3'], fs.exists, function(result){
Osamu Nakamura 0:a40b9a259b52 604 // if result is true then at least one of the files exists
Osamu Nakamura 0:a40b9a259b52 605 });
Osamu Nakamura 0:a40b9a259b52 606 ```
Osamu Nakamura 0:a40b9a259b52 607
Osamu Nakamura 0:a40b9a259b52 608 __Related__
Osamu Nakamura 0:a40b9a259b52 609
Osamu Nakamura 0:a40b9a259b52 610 * someLimit(arr, limit, iterator, callback)
Osamu Nakamura 0:a40b9a259b52 611
Osamu Nakamura 0:a40b9a259b52 612 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 613
Osamu Nakamura 0:a40b9a259b52 614 <a name="every" />
Osamu Nakamura 0:a40b9a259b52 615 ### every(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 616
Osamu Nakamura 0:a40b9a259b52 617 __Alias:__ `all`
Osamu Nakamura 0:a40b9a259b52 618
Osamu Nakamura 0:a40b9a259b52 619 Returns `true` if every element in `arr` satisfies an async test.
Osamu Nakamura 0:a40b9a259b52 620 _The callback for each `iterator` call only accepts a single argument of `true` or
Osamu Nakamura 0:a40b9a259b52 621 `false`; it does not accept an error argument first!_ This is in-line with the
Osamu Nakamura 0:a40b9a259b52 622 way node libraries work with truth tests like `fs.exists`.
Osamu Nakamura 0:a40b9a259b52 623
Osamu Nakamura 0:a40b9a259b52 624 __Arguments__
Osamu Nakamura 0:a40b9a259b52 625
Osamu Nakamura 0:a40b9a259b52 626 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 627 * `iterator(item, callback)` - A truth test to apply to each item in the array
Osamu Nakamura 0:a40b9a259b52 628 in parallel. The iterator is passed a `callback(truthValue)` which must be
Osamu Nakamura 0:a40b9a259b52 629 called with a boolean argument once it has completed.
Osamu Nakamura 0:a40b9a259b52 630 * `callback(result)` - *Optional* A callback which is called as soon as any iterator returns
Osamu Nakamura 0:a40b9a259b52 631 `false`, or after all the iterator functions have finished. Result will be
Osamu Nakamura 0:a40b9a259b52 632 either `true` or `false` depending on the values of the async tests.
Osamu Nakamura 0:a40b9a259b52 633
Osamu Nakamura 0:a40b9a259b52 634 **Note: the callbacks do not take an error as their first argument.**
Osamu Nakamura 0:a40b9a259b52 635
Osamu Nakamura 0:a40b9a259b52 636 __Example__
Osamu Nakamura 0:a40b9a259b52 637
Osamu Nakamura 0:a40b9a259b52 638 ```js
Osamu Nakamura 0:a40b9a259b52 639 async.every(['file1','file2','file3'], fs.exists, function(result){
Osamu Nakamura 0:a40b9a259b52 640 // if result is true then every file exists
Osamu Nakamura 0:a40b9a259b52 641 });
Osamu Nakamura 0:a40b9a259b52 642 ```
Osamu Nakamura 0:a40b9a259b52 643
Osamu Nakamura 0:a40b9a259b52 644 __Related__
Osamu Nakamura 0:a40b9a259b52 645
Osamu Nakamura 0:a40b9a259b52 646 * everyLimit(arr, limit, iterator, callback)
Osamu Nakamura 0:a40b9a259b52 647
Osamu Nakamura 0:a40b9a259b52 648 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 649
Osamu Nakamura 0:a40b9a259b52 650 <a name="concat" />
Osamu Nakamura 0:a40b9a259b52 651 ### concat(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 652
Osamu Nakamura 0:a40b9a259b52 653 Applies `iterator` to each item in `arr`, concatenating the results. Returns the
Osamu Nakamura 0:a40b9a259b52 654 concatenated list. The `iterator`s are called in parallel, and the results are
Osamu Nakamura 0:a40b9a259b52 655 concatenated as they return. There is no guarantee that the results array will
Osamu Nakamura 0:a40b9a259b52 656 be returned in the original order of `arr` passed to the `iterator` function.
Osamu Nakamura 0:a40b9a259b52 657
Osamu Nakamura 0:a40b9a259b52 658 __Arguments__
Osamu Nakamura 0:a40b9a259b52 659
Osamu Nakamura 0:a40b9a259b52 660 * `arr` - An array to iterate over.
Osamu Nakamura 0:a40b9a259b52 661 * `iterator(item, callback)` - A function to apply to each item in `arr`.
Osamu Nakamura 0:a40b9a259b52 662 The iterator is passed a `callback(err, results)` which must be called once it
Osamu Nakamura 0:a40b9a259b52 663 has completed with an error (which can be `null`) and an array of results.
Osamu Nakamura 0:a40b9a259b52 664 * `callback(err, results)` - *Optional* A callback which is called after all the `iterator`
Osamu Nakamura 0:a40b9a259b52 665 functions have finished, or an error occurs. Results is an array containing
Osamu Nakamura 0:a40b9a259b52 666 the concatenated results of the `iterator` function.
Osamu Nakamura 0:a40b9a259b52 667
Osamu Nakamura 0:a40b9a259b52 668 __Example__
Osamu Nakamura 0:a40b9a259b52 669
Osamu Nakamura 0:a40b9a259b52 670 ```js
Osamu Nakamura 0:a40b9a259b52 671 async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){
Osamu Nakamura 0:a40b9a259b52 672 // files is now a list of filenames that exist in the 3 directories
Osamu Nakamura 0:a40b9a259b52 673 });
Osamu Nakamura 0:a40b9a259b52 674 ```
Osamu Nakamura 0:a40b9a259b52 675
Osamu Nakamura 0:a40b9a259b52 676 __Related__
Osamu Nakamura 0:a40b9a259b52 677
Osamu Nakamura 0:a40b9a259b52 678 * concatSeries(arr, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 679
Osamu Nakamura 0:a40b9a259b52 680
Osamu Nakamura 0:a40b9a259b52 681 ## Control Flow
Osamu Nakamura 0:a40b9a259b52 682
Osamu Nakamura 0:a40b9a259b52 683 <a name="series" />
Osamu Nakamura 0:a40b9a259b52 684 ### series(tasks, [callback])
Osamu Nakamura 0:a40b9a259b52 685
Osamu Nakamura 0:a40b9a259b52 686 Run the functions in the `tasks` array in series, each one running once the previous
Osamu Nakamura 0:a40b9a259b52 687 function has completed. If any functions in the series pass an error to its
Osamu Nakamura 0:a40b9a259b52 688 callback, no more functions are run, and `callback` is immediately called with the value of the error.
Osamu Nakamura 0:a40b9a259b52 689 Otherwise, `callback` receives an array of results when `tasks` have completed.
Osamu Nakamura 0:a40b9a259b52 690
Osamu Nakamura 0:a40b9a259b52 691 It is also possible to use an object instead of an array. Each property will be
Osamu Nakamura 0:a40b9a259b52 692 run as a function, and the results will be passed to the final `callback` as an object
Osamu Nakamura 0:a40b9a259b52 693 instead of an array. This can be a more readable way of handling results from
Osamu Nakamura 0:a40b9a259b52 694 [`series`](#series).
Osamu Nakamura 0:a40b9a259b52 695
Osamu Nakamura 0:a40b9a259b52 696 **Note** that while many implementations preserve the order of object properties, the
Osamu Nakamura 0:a40b9a259b52 697 [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6)
Osamu Nakamura 0:a40b9a259b52 698 explicitly states that
Osamu Nakamura 0:a40b9a259b52 699
Osamu Nakamura 0:a40b9a259b52 700 > The mechanics and order of enumerating the properties is not specified.
Osamu Nakamura 0:a40b9a259b52 701
Osamu Nakamura 0:a40b9a259b52 702 So if you rely on the order in which your series of functions are executed, and want
Osamu Nakamura 0:a40b9a259b52 703 this to work on all platforms, consider using an array.
Osamu Nakamura 0:a40b9a259b52 704
Osamu Nakamura 0:a40b9a259b52 705 __Arguments__
Osamu Nakamura 0:a40b9a259b52 706
Osamu Nakamura 0:a40b9a259b52 707 * `tasks` - An array or object containing functions to run, each function is passed
Osamu Nakamura 0:a40b9a259b52 708 a `callback(err, result)` it must call on completion with an error `err` (which can
Osamu Nakamura 0:a40b9a259b52 709 be `null`) and an optional `result` value.
Osamu Nakamura 0:a40b9a259b52 710 * `callback(err, results)` - An optional callback to run once all the functions
Osamu Nakamura 0:a40b9a259b52 711 have completed. This function gets a results array (or object) containing all
Osamu Nakamura 0:a40b9a259b52 712 the result arguments passed to the `task` callbacks.
Osamu Nakamura 0:a40b9a259b52 713
Osamu Nakamura 0:a40b9a259b52 714 __Example__
Osamu Nakamura 0:a40b9a259b52 715
Osamu Nakamura 0:a40b9a259b52 716 ```js
Osamu Nakamura 0:a40b9a259b52 717 async.series([
Osamu Nakamura 0:a40b9a259b52 718 function(callback){
Osamu Nakamura 0:a40b9a259b52 719 // do some stuff ...
Osamu Nakamura 0:a40b9a259b52 720 callback(null, 'one');
Osamu Nakamura 0:a40b9a259b52 721 },
Osamu Nakamura 0:a40b9a259b52 722 function(callback){
Osamu Nakamura 0:a40b9a259b52 723 // do some more stuff ...
Osamu Nakamura 0:a40b9a259b52 724 callback(null, 'two');
Osamu Nakamura 0:a40b9a259b52 725 }
Osamu Nakamura 0:a40b9a259b52 726 ],
Osamu Nakamura 0:a40b9a259b52 727 // optional callback
Osamu Nakamura 0:a40b9a259b52 728 function(err, results){
Osamu Nakamura 0:a40b9a259b52 729 // results is now equal to ['one', 'two']
Osamu Nakamura 0:a40b9a259b52 730 });
Osamu Nakamura 0:a40b9a259b52 731
Osamu Nakamura 0:a40b9a259b52 732
Osamu Nakamura 0:a40b9a259b52 733 // an example using an object instead of an array
Osamu Nakamura 0:a40b9a259b52 734 async.series({
Osamu Nakamura 0:a40b9a259b52 735 one: function(callback){
Osamu Nakamura 0:a40b9a259b52 736 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 737 callback(null, 1);
Osamu Nakamura 0:a40b9a259b52 738 }, 200);
Osamu Nakamura 0:a40b9a259b52 739 },
Osamu Nakamura 0:a40b9a259b52 740 two: function(callback){
Osamu Nakamura 0:a40b9a259b52 741 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 742 callback(null, 2);
Osamu Nakamura 0:a40b9a259b52 743 }, 100);
Osamu Nakamura 0:a40b9a259b52 744 }
Osamu Nakamura 0:a40b9a259b52 745 },
Osamu Nakamura 0:a40b9a259b52 746 function(err, results) {
Osamu Nakamura 0:a40b9a259b52 747 // results is now equal to: {one: 1, two: 2}
Osamu Nakamura 0:a40b9a259b52 748 });
Osamu Nakamura 0:a40b9a259b52 749 ```
Osamu Nakamura 0:a40b9a259b52 750
Osamu Nakamura 0:a40b9a259b52 751 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 752
Osamu Nakamura 0:a40b9a259b52 753 <a name="parallel" />
Osamu Nakamura 0:a40b9a259b52 754 ### parallel(tasks, [callback])
Osamu Nakamura 0:a40b9a259b52 755
Osamu Nakamura 0:a40b9a259b52 756 Run the `tasks` array of functions in parallel, without waiting until the previous
Osamu Nakamura 0:a40b9a259b52 757 function has completed. If any of the functions pass an error to its
Osamu Nakamura 0:a40b9a259b52 758 callback, the main `callback` is immediately called with the value of the error.
Osamu Nakamura 0:a40b9a259b52 759 Once the `tasks` have completed, the results are passed to the final `callback` as an
Osamu Nakamura 0:a40b9a259b52 760 array.
Osamu Nakamura 0:a40b9a259b52 761
Osamu Nakamura 0:a40b9a259b52 762 **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about parallel execution of code. If your tasks do not use any timers or perform any I/O, they will actually be executed in series. Any synchronous setup sections for each task will happen one after the other. JavaScript remains single-threaded.
Osamu Nakamura 0:a40b9a259b52 763
Osamu Nakamura 0:a40b9a259b52 764 It is also possible to use an object instead of an array. Each property will be
Osamu Nakamura 0:a40b9a259b52 765 run as a function and the results will be passed to the final `callback` as an object
Osamu Nakamura 0:a40b9a259b52 766 instead of an array. This can be a more readable way of handling results from
Osamu Nakamura 0:a40b9a259b52 767 [`parallel`](#parallel).
Osamu Nakamura 0:a40b9a259b52 768
Osamu Nakamura 0:a40b9a259b52 769
Osamu Nakamura 0:a40b9a259b52 770 __Arguments__
Osamu Nakamura 0:a40b9a259b52 771
Osamu Nakamura 0:a40b9a259b52 772 * `tasks` - An array or object containing functions to run. Each function is passed
Osamu Nakamura 0:a40b9a259b52 773 a `callback(err, result)` which it must call on completion with an error `err`
Osamu Nakamura 0:a40b9a259b52 774 (which can be `null`) and an optional `result` value.
Osamu Nakamura 0:a40b9a259b52 775 * `callback(err, results)` - An optional callback to run once all the functions
Osamu Nakamura 0:a40b9a259b52 776 have completed successfully. This function gets a results array (or object) containing all
Osamu Nakamura 0:a40b9a259b52 777 the result arguments passed to the task callbacks.
Osamu Nakamura 0:a40b9a259b52 778
Osamu Nakamura 0:a40b9a259b52 779 __Example__
Osamu Nakamura 0:a40b9a259b52 780
Osamu Nakamura 0:a40b9a259b52 781 ```js
Osamu Nakamura 0:a40b9a259b52 782 async.parallel([
Osamu Nakamura 0:a40b9a259b52 783 function(callback){
Osamu Nakamura 0:a40b9a259b52 784 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 785 callback(null, 'one');
Osamu Nakamura 0:a40b9a259b52 786 }, 200);
Osamu Nakamura 0:a40b9a259b52 787 },
Osamu Nakamura 0:a40b9a259b52 788 function(callback){
Osamu Nakamura 0:a40b9a259b52 789 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 790 callback(null, 'two');
Osamu Nakamura 0:a40b9a259b52 791 }, 100);
Osamu Nakamura 0:a40b9a259b52 792 }
Osamu Nakamura 0:a40b9a259b52 793 ],
Osamu Nakamura 0:a40b9a259b52 794 // optional callback
Osamu Nakamura 0:a40b9a259b52 795 function(err, results){
Osamu Nakamura 0:a40b9a259b52 796 // the results array will equal ['one','two'] even though
Osamu Nakamura 0:a40b9a259b52 797 // the second function had a shorter timeout.
Osamu Nakamura 0:a40b9a259b52 798 });
Osamu Nakamura 0:a40b9a259b52 799
Osamu Nakamura 0:a40b9a259b52 800
Osamu Nakamura 0:a40b9a259b52 801 // an example using an object instead of an array
Osamu Nakamura 0:a40b9a259b52 802 async.parallel({
Osamu Nakamura 0:a40b9a259b52 803 one: function(callback){
Osamu Nakamura 0:a40b9a259b52 804 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 805 callback(null, 1);
Osamu Nakamura 0:a40b9a259b52 806 }, 200);
Osamu Nakamura 0:a40b9a259b52 807 },
Osamu Nakamura 0:a40b9a259b52 808 two: function(callback){
Osamu Nakamura 0:a40b9a259b52 809 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 810 callback(null, 2);
Osamu Nakamura 0:a40b9a259b52 811 }, 100);
Osamu Nakamura 0:a40b9a259b52 812 }
Osamu Nakamura 0:a40b9a259b52 813 },
Osamu Nakamura 0:a40b9a259b52 814 function(err, results) {
Osamu Nakamura 0:a40b9a259b52 815 // results is now equals to: {one: 1, two: 2}
Osamu Nakamura 0:a40b9a259b52 816 });
Osamu Nakamura 0:a40b9a259b52 817 ```
Osamu Nakamura 0:a40b9a259b52 818
Osamu Nakamura 0:a40b9a259b52 819 __Related__
Osamu Nakamura 0:a40b9a259b52 820
Osamu Nakamura 0:a40b9a259b52 821 * parallelLimit(tasks, limit, [callback])
Osamu Nakamura 0:a40b9a259b52 822
Osamu Nakamura 0:a40b9a259b52 823 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 824
Osamu Nakamura 0:a40b9a259b52 825 <a name="whilst" />
Osamu Nakamura 0:a40b9a259b52 826 ### whilst(test, fn, callback)
Osamu Nakamura 0:a40b9a259b52 827
Osamu Nakamura 0:a40b9a259b52 828 Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped,
Osamu Nakamura 0:a40b9a259b52 829 or an error occurs.
Osamu Nakamura 0:a40b9a259b52 830
Osamu Nakamura 0:a40b9a259b52 831 __Arguments__
Osamu Nakamura 0:a40b9a259b52 832
Osamu Nakamura 0:a40b9a259b52 833 * `test()` - synchronous truth test to perform before each execution of `fn`.
Osamu Nakamura 0:a40b9a259b52 834 * `fn(callback)` - A function which is called each time `test` passes. The function is
Osamu Nakamura 0:a40b9a259b52 835 passed a `callback(err)`, which must be called once it has completed with an
Osamu Nakamura 0:a40b9a259b52 836 optional `err` argument.
Osamu Nakamura 0:a40b9a259b52 837 * `callback(err, [results])` - A callback which is called after the test
Osamu Nakamura 0:a40b9a259b52 838 function has failed and repeated execution of `fn` has stopped. `callback`
Osamu Nakamura 0:a40b9a259b52 839 will be passed an error and any arguments passed to the final `fn`'s callback.
Osamu Nakamura 0:a40b9a259b52 840
Osamu Nakamura 0:a40b9a259b52 841 __Example__
Osamu Nakamura 0:a40b9a259b52 842
Osamu Nakamura 0:a40b9a259b52 843 ```js
Osamu Nakamura 0:a40b9a259b52 844 var count = 0;
Osamu Nakamura 0:a40b9a259b52 845
Osamu Nakamura 0:a40b9a259b52 846 async.whilst(
Osamu Nakamura 0:a40b9a259b52 847 function () { return count < 5; },
Osamu Nakamura 0:a40b9a259b52 848 function (callback) {
Osamu Nakamura 0:a40b9a259b52 849 count++;
Osamu Nakamura 0:a40b9a259b52 850 setTimeout(function () {
Osamu Nakamura 0:a40b9a259b52 851 callback(null, count);
Osamu Nakamura 0:a40b9a259b52 852 }, 1000);
Osamu Nakamura 0:a40b9a259b52 853 },
Osamu Nakamura 0:a40b9a259b52 854 function (err, n) {
Osamu Nakamura 0:a40b9a259b52 855 // 5 seconds have passed, n = 5
Osamu Nakamura 0:a40b9a259b52 856 }
Osamu Nakamura 0:a40b9a259b52 857 );
Osamu Nakamura 0:a40b9a259b52 858 ```
Osamu Nakamura 0:a40b9a259b52 859
Osamu Nakamura 0:a40b9a259b52 860 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 861
Osamu Nakamura 0:a40b9a259b52 862 <a name="doWhilst" />
Osamu Nakamura 0:a40b9a259b52 863 ### doWhilst(fn, test, callback)
Osamu Nakamura 0:a40b9a259b52 864
Osamu Nakamura 0:a40b9a259b52 865 The post-check version of [`whilst`](#whilst). To reflect the difference in
Osamu Nakamura 0:a40b9a259b52 866 the order of operations, the arguments `test` and `fn` are switched.
Osamu Nakamura 0:a40b9a259b52 867
Osamu Nakamura 0:a40b9a259b52 868 `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
Osamu Nakamura 0:a40b9a259b52 869
Osamu Nakamura 0:a40b9a259b52 870 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 871
Osamu Nakamura 0:a40b9a259b52 872 <a name="until" />
Osamu Nakamura 0:a40b9a259b52 873 ### until(test, fn, callback)
Osamu Nakamura 0:a40b9a259b52 874
Osamu Nakamura 0:a40b9a259b52 875 Repeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped,
Osamu Nakamura 0:a40b9a259b52 876 or an error occurs. `callback` will be passed an error and any arguments passed
Osamu Nakamura 0:a40b9a259b52 877 to the final `fn`'s callback.
Osamu Nakamura 0:a40b9a259b52 878
Osamu Nakamura 0:a40b9a259b52 879 The inverse of [`whilst`](#whilst).
Osamu Nakamura 0:a40b9a259b52 880
Osamu Nakamura 0:a40b9a259b52 881 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 882
Osamu Nakamura 0:a40b9a259b52 883 <a name="doUntil" />
Osamu Nakamura 0:a40b9a259b52 884 ### doUntil(fn, test, callback)
Osamu Nakamura 0:a40b9a259b52 885
Osamu Nakamura 0:a40b9a259b52 886 Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`.
Osamu Nakamura 0:a40b9a259b52 887
Osamu Nakamura 0:a40b9a259b52 888 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 889
Osamu Nakamura 0:a40b9a259b52 890 <a name="during" />
Osamu Nakamura 0:a40b9a259b52 891 ### during(test, fn, callback)
Osamu Nakamura 0:a40b9a259b52 892
Osamu Nakamura 0:a40b9a259b52 893 Like [`whilst`](#whilst), except the `test` is an asynchronous function that is passed a callback in the form of `function (err, truth)`. If error is passed to `test` or `fn`, the main callback is immediately called with the value of the error.
Osamu Nakamura 0:a40b9a259b52 894
Osamu Nakamura 0:a40b9a259b52 895 __Example__
Osamu Nakamura 0:a40b9a259b52 896
Osamu Nakamura 0:a40b9a259b52 897 ```js
Osamu Nakamura 0:a40b9a259b52 898 var count = 0;
Osamu Nakamura 0:a40b9a259b52 899
Osamu Nakamura 0:a40b9a259b52 900 async.during(
Osamu Nakamura 0:a40b9a259b52 901 function (callback) {
Osamu Nakamura 0:a40b9a259b52 902 return callback(null, count < 5);
Osamu Nakamura 0:a40b9a259b52 903 },
Osamu Nakamura 0:a40b9a259b52 904 function (callback) {
Osamu Nakamura 0:a40b9a259b52 905 count++;
Osamu Nakamura 0:a40b9a259b52 906 setTimeout(callback, 1000);
Osamu Nakamura 0:a40b9a259b52 907 },
Osamu Nakamura 0:a40b9a259b52 908 function (err) {
Osamu Nakamura 0:a40b9a259b52 909 // 5 seconds have passed
Osamu Nakamura 0:a40b9a259b52 910 }
Osamu Nakamura 0:a40b9a259b52 911 );
Osamu Nakamura 0:a40b9a259b52 912 ```
Osamu Nakamura 0:a40b9a259b52 913
Osamu Nakamura 0:a40b9a259b52 914 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 915
Osamu Nakamura 0:a40b9a259b52 916 <a name="doDuring" />
Osamu Nakamura 0:a40b9a259b52 917 ### doDuring(fn, test, callback)
Osamu Nakamura 0:a40b9a259b52 918
Osamu Nakamura 0:a40b9a259b52 919 The post-check version of [`during`](#during). To reflect the difference in
Osamu Nakamura 0:a40b9a259b52 920 the order of operations, the arguments `test` and `fn` are switched.
Osamu Nakamura 0:a40b9a259b52 921
Osamu Nakamura 0:a40b9a259b52 922 Also a version of [`doWhilst`](#doWhilst) with asynchronous `test` function.
Osamu Nakamura 0:a40b9a259b52 923
Osamu Nakamura 0:a40b9a259b52 924 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 925
Osamu Nakamura 0:a40b9a259b52 926 <a name="forever" />
Osamu Nakamura 0:a40b9a259b52 927 ### forever(fn, [errback])
Osamu Nakamura 0:a40b9a259b52 928
Osamu Nakamura 0:a40b9a259b52 929 Calls the asynchronous function `fn` with a callback parameter that allows it to
Osamu Nakamura 0:a40b9a259b52 930 call itself again, in series, indefinitely.
Osamu Nakamura 0:a40b9a259b52 931
Osamu Nakamura 0:a40b9a259b52 932 If an error is passed to the callback then `errback` is called with the
Osamu Nakamura 0:a40b9a259b52 933 error, and execution stops, otherwise it will never be called.
Osamu Nakamura 0:a40b9a259b52 934
Osamu Nakamura 0:a40b9a259b52 935 ```js
Osamu Nakamura 0:a40b9a259b52 936 async.forever(
Osamu Nakamura 0:a40b9a259b52 937 function(next) {
Osamu Nakamura 0:a40b9a259b52 938 // next is suitable for passing to things that need a callback(err [, whatever]);
Osamu Nakamura 0:a40b9a259b52 939 // it will result in this function being called again.
Osamu Nakamura 0:a40b9a259b52 940 },
Osamu Nakamura 0:a40b9a259b52 941 function(err) {
Osamu Nakamura 0:a40b9a259b52 942 // if next is called with a value in its first parameter, it will appear
Osamu Nakamura 0:a40b9a259b52 943 // in here as 'err', and execution will stop.
Osamu Nakamura 0:a40b9a259b52 944 }
Osamu Nakamura 0:a40b9a259b52 945 );
Osamu Nakamura 0:a40b9a259b52 946 ```
Osamu Nakamura 0:a40b9a259b52 947
Osamu Nakamura 0:a40b9a259b52 948 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 949
Osamu Nakamura 0:a40b9a259b52 950 <a name="waterfall" />
Osamu Nakamura 0:a40b9a259b52 951 ### waterfall(tasks, [callback])
Osamu Nakamura 0:a40b9a259b52 952
Osamu Nakamura 0:a40b9a259b52 953 Runs the `tasks` array of functions in series, each passing their results to the next in
Osamu Nakamura 0:a40b9a259b52 954 the array. However, if any of the `tasks` pass an error to their own callback, the
Osamu Nakamura 0:a40b9a259b52 955 next function is not executed, and the main `callback` is immediately called with
Osamu Nakamura 0:a40b9a259b52 956 the error.
Osamu Nakamura 0:a40b9a259b52 957
Osamu Nakamura 0:a40b9a259b52 958 __Arguments__
Osamu Nakamura 0:a40b9a259b52 959
Osamu Nakamura 0:a40b9a259b52 960 * `tasks` - An array of functions to run, each function is passed a
Osamu Nakamura 0:a40b9a259b52 961 `callback(err, result1, result2, ...)` it must call on completion. The first
Osamu Nakamura 0:a40b9a259b52 962 argument is an error (which can be `null`) and any further arguments will be
Osamu Nakamura 0:a40b9a259b52 963 passed as arguments in order to the next task.
Osamu Nakamura 0:a40b9a259b52 964 * `callback(err, [results])` - An optional callback to run once all the functions
Osamu Nakamura 0:a40b9a259b52 965 have completed. This will be passed the results of the last task's callback.
Osamu Nakamura 0:a40b9a259b52 966
Osamu Nakamura 0:a40b9a259b52 967
Osamu Nakamura 0:a40b9a259b52 968
Osamu Nakamura 0:a40b9a259b52 969 __Example__
Osamu Nakamura 0:a40b9a259b52 970
Osamu Nakamura 0:a40b9a259b52 971 ```js
Osamu Nakamura 0:a40b9a259b52 972 async.waterfall([
Osamu Nakamura 0:a40b9a259b52 973 function(callback) {
Osamu Nakamura 0:a40b9a259b52 974 callback(null, 'one', 'two');
Osamu Nakamura 0:a40b9a259b52 975 },
Osamu Nakamura 0:a40b9a259b52 976 function(arg1, arg2, callback) {
Osamu Nakamura 0:a40b9a259b52 977 // arg1 now equals 'one' and arg2 now equals 'two'
Osamu Nakamura 0:a40b9a259b52 978 callback(null, 'three');
Osamu Nakamura 0:a40b9a259b52 979 },
Osamu Nakamura 0:a40b9a259b52 980 function(arg1, callback) {
Osamu Nakamura 0:a40b9a259b52 981 // arg1 now equals 'three'
Osamu Nakamura 0:a40b9a259b52 982 callback(null, 'done');
Osamu Nakamura 0:a40b9a259b52 983 }
Osamu Nakamura 0:a40b9a259b52 984 ], function (err, result) {
Osamu Nakamura 0:a40b9a259b52 985 // result now equals 'done'
Osamu Nakamura 0:a40b9a259b52 986 });
Osamu Nakamura 0:a40b9a259b52 987 ```
Osamu Nakamura 0:a40b9a259b52 988 Or, with named functions:
Osamu Nakamura 0:a40b9a259b52 989
Osamu Nakamura 0:a40b9a259b52 990 ```js
Osamu Nakamura 0:a40b9a259b52 991 async.waterfall([
Osamu Nakamura 0:a40b9a259b52 992 myFirstFunction,
Osamu Nakamura 0:a40b9a259b52 993 mySecondFunction,
Osamu Nakamura 0:a40b9a259b52 994 myLastFunction,
Osamu Nakamura 0:a40b9a259b52 995 ], function (err, result) {
Osamu Nakamura 0:a40b9a259b52 996 // result now equals 'done'
Osamu Nakamura 0:a40b9a259b52 997 });
Osamu Nakamura 0:a40b9a259b52 998 function myFirstFunction(callback) {
Osamu Nakamura 0:a40b9a259b52 999 callback(null, 'one', 'two');
Osamu Nakamura 0:a40b9a259b52 1000 }
Osamu Nakamura 0:a40b9a259b52 1001 function mySecondFunction(arg1, arg2, callback) {
Osamu Nakamura 0:a40b9a259b52 1002 // arg1 now equals 'one' and arg2 now equals 'two'
Osamu Nakamura 0:a40b9a259b52 1003 callback(null, 'three');
Osamu Nakamura 0:a40b9a259b52 1004 }
Osamu Nakamura 0:a40b9a259b52 1005 function myLastFunction(arg1, callback) {
Osamu Nakamura 0:a40b9a259b52 1006 // arg1 now equals 'three'
Osamu Nakamura 0:a40b9a259b52 1007 callback(null, 'done');
Osamu Nakamura 0:a40b9a259b52 1008 }
Osamu Nakamura 0:a40b9a259b52 1009 ```
Osamu Nakamura 0:a40b9a259b52 1010
Osamu Nakamura 0:a40b9a259b52 1011 Or, if you need to pass any argument to the first function:
Osamu Nakamura 0:a40b9a259b52 1012
Osamu Nakamura 0:a40b9a259b52 1013 ```js
Osamu Nakamura 0:a40b9a259b52 1014 async.waterfall([
Osamu Nakamura 0:a40b9a259b52 1015 async.apply(myFirstFunction, 'zero'),
Osamu Nakamura 0:a40b9a259b52 1016 mySecondFunction,
Osamu Nakamura 0:a40b9a259b52 1017 myLastFunction,
Osamu Nakamura 0:a40b9a259b52 1018 ], function (err, result) {
Osamu Nakamura 0:a40b9a259b52 1019 // result now equals 'done'
Osamu Nakamura 0:a40b9a259b52 1020 });
Osamu Nakamura 0:a40b9a259b52 1021 function myFirstFunction(arg1, callback) {
Osamu Nakamura 0:a40b9a259b52 1022 // arg1 now equals 'zero'
Osamu Nakamura 0:a40b9a259b52 1023 callback(null, 'one', 'two');
Osamu Nakamura 0:a40b9a259b52 1024 }
Osamu Nakamura 0:a40b9a259b52 1025 function mySecondFunction(arg1, arg2, callback) {
Osamu Nakamura 0:a40b9a259b52 1026 // arg1 now equals 'one' and arg2 now equals 'two'
Osamu Nakamura 0:a40b9a259b52 1027 callback(null, 'three');
Osamu Nakamura 0:a40b9a259b52 1028 }
Osamu Nakamura 0:a40b9a259b52 1029 function myLastFunction(arg1, callback) {
Osamu Nakamura 0:a40b9a259b52 1030 // arg1 now equals 'three'
Osamu Nakamura 0:a40b9a259b52 1031 callback(null, 'done');
Osamu Nakamura 0:a40b9a259b52 1032 }
Osamu Nakamura 0:a40b9a259b52 1033 ```
Osamu Nakamura 0:a40b9a259b52 1034
Osamu Nakamura 0:a40b9a259b52 1035 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1036 <a name="compose" />
Osamu Nakamura 0:a40b9a259b52 1037 ### compose(fn1, fn2...)
Osamu Nakamura 0:a40b9a259b52 1038
Osamu Nakamura 0:a40b9a259b52 1039 Creates a function which is a composition of the passed asynchronous
Osamu Nakamura 0:a40b9a259b52 1040 functions. Each function consumes the return value of the function that
Osamu Nakamura 0:a40b9a259b52 1041 follows. Composing functions `f()`, `g()`, and `h()` would produce the result of
Osamu Nakamura 0:a40b9a259b52 1042 `f(g(h()))`, only this version uses callbacks to obtain the return values.
Osamu Nakamura 0:a40b9a259b52 1043
Osamu Nakamura 0:a40b9a259b52 1044 Each function is executed with the `this` binding of the composed function.
Osamu Nakamura 0:a40b9a259b52 1045
Osamu Nakamura 0:a40b9a259b52 1046 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1047
Osamu Nakamura 0:a40b9a259b52 1048 * `functions...` - the asynchronous functions to compose
Osamu Nakamura 0:a40b9a259b52 1049
Osamu Nakamura 0:a40b9a259b52 1050
Osamu Nakamura 0:a40b9a259b52 1051 __Example__
Osamu Nakamura 0:a40b9a259b52 1052
Osamu Nakamura 0:a40b9a259b52 1053 ```js
Osamu Nakamura 0:a40b9a259b52 1054 function add1(n, callback) {
Osamu Nakamura 0:a40b9a259b52 1055 setTimeout(function () {
Osamu Nakamura 0:a40b9a259b52 1056 callback(null, n + 1);
Osamu Nakamura 0:a40b9a259b52 1057 }, 10);
Osamu Nakamura 0:a40b9a259b52 1058 }
Osamu Nakamura 0:a40b9a259b52 1059
Osamu Nakamura 0:a40b9a259b52 1060 function mul3(n, callback) {
Osamu Nakamura 0:a40b9a259b52 1061 setTimeout(function () {
Osamu Nakamura 0:a40b9a259b52 1062 callback(null, n * 3);
Osamu Nakamura 0:a40b9a259b52 1063 }, 10);
Osamu Nakamura 0:a40b9a259b52 1064 }
Osamu Nakamura 0:a40b9a259b52 1065
Osamu Nakamura 0:a40b9a259b52 1066 var add1mul3 = async.compose(mul3, add1);
Osamu Nakamura 0:a40b9a259b52 1067
Osamu Nakamura 0:a40b9a259b52 1068 add1mul3(4, function (err, result) {
Osamu Nakamura 0:a40b9a259b52 1069 // result now equals 15
Osamu Nakamura 0:a40b9a259b52 1070 });
Osamu Nakamura 0:a40b9a259b52 1071 ```
Osamu Nakamura 0:a40b9a259b52 1072
Osamu Nakamura 0:a40b9a259b52 1073 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1074 <a name="seq" />
Osamu Nakamura 0:a40b9a259b52 1075 ### seq(fn1, fn2...)
Osamu Nakamura 0:a40b9a259b52 1076
Osamu Nakamura 0:a40b9a259b52 1077 Version of the compose function that is more natural to read.
Osamu Nakamura 0:a40b9a259b52 1078 Each function consumes the return value of the previous function.
Osamu Nakamura 0:a40b9a259b52 1079 It is the equivalent of [`compose`](#compose) with the arguments reversed.
Osamu Nakamura 0:a40b9a259b52 1080
Osamu Nakamura 0:a40b9a259b52 1081 Each function is executed with the `this` binding of the composed function.
Osamu Nakamura 0:a40b9a259b52 1082
Osamu Nakamura 0:a40b9a259b52 1083 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1084
Osamu Nakamura 0:a40b9a259b52 1085 * `functions...` - the asynchronous functions to compose
Osamu Nakamura 0:a40b9a259b52 1086
Osamu Nakamura 0:a40b9a259b52 1087
Osamu Nakamura 0:a40b9a259b52 1088 __Example__
Osamu Nakamura 0:a40b9a259b52 1089
Osamu Nakamura 0:a40b9a259b52 1090 ```js
Osamu Nakamura 0:a40b9a259b52 1091 // Requires lodash (or underscore), express3 and dresende's orm2.
Osamu Nakamura 0:a40b9a259b52 1092 // Part of an app, that fetches cats of the logged user.
Osamu Nakamura 0:a40b9a259b52 1093 // This example uses `seq` function to avoid overnesting and error
Osamu Nakamura 0:a40b9a259b52 1094 // handling clutter.
Osamu Nakamura 0:a40b9a259b52 1095 app.get('/cats', function(request, response) {
Osamu Nakamura 0:a40b9a259b52 1096 var User = request.models.User;
Osamu Nakamura 0:a40b9a259b52 1097 async.seq(
Osamu Nakamura 0:a40b9a259b52 1098 _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data))
Osamu Nakamura 0:a40b9a259b52 1099 function(user, fn) {
Osamu Nakamura 0:a40b9a259b52 1100 user.getCats(fn); // 'getCats' has signature (callback(err, data))
Osamu Nakamura 0:a40b9a259b52 1101 }
Osamu Nakamura 0:a40b9a259b52 1102 )(req.session.user_id, function (err, cats) {
Osamu Nakamura 0:a40b9a259b52 1103 if (err) {
Osamu Nakamura 0:a40b9a259b52 1104 console.error(err);
Osamu Nakamura 0:a40b9a259b52 1105 response.json({ status: 'error', message: err.message });
Osamu Nakamura 0:a40b9a259b52 1106 } else {
Osamu Nakamura 0:a40b9a259b52 1107 response.json({ status: 'ok', message: 'Cats found', data: cats });
Osamu Nakamura 0:a40b9a259b52 1108 }
Osamu Nakamura 0:a40b9a259b52 1109 });
Osamu Nakamura 0:a40b9a259b52 1110 });
Osamu Nakamura 0:a40b9a259b52 1111 ```
Osamu Nakamura 0:a40b9a259b52 1112
Osamu Nakamura 0:a40b9a259b52 1113 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1114 <a name="applyEach" />
Osamu Nakamura 0:a40b9a259b52 1115 ### applyEach(fns, args..., callback)
Osamu Nakamura 0:a40b9a259b52 1116
Osamu Nakamura 0:a40b9a259b52 1117 Applies the provided arguments to each function in the array, calling
Osamu Nakamura 0:a40b9a259b52 1118 `callback` after all functions have completed. If you only provide the first
Osamu Nakamura 0:a40b9a259b52 1119 argument, then it will return a function which lets you pass in the
Osamu Nakamura 0:a40b9a259b52 1120 arguments as if it were a single function call.
Osamu Nakamura 0:a40b9a259b52 1121
Osamu Nakamura 0:a40b9a259b52 1122 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1123
Osamu Nakamura 0:a40b9a259b52 1124 * `fns` - the asynchronous functions to all call with the same arguments
Osamu Nakamura 0:a40b9a259b52 1125 * `args...` - any number of separate arguments to pass to the function
Osamu Nakamura 0:a40b9a259b52 1126 * `callback` - the final argument should be the callback, called when all
Osamu Nakamura 0:a40b9a259b52 1127 functions have completed processing
Osamu Nakamura 0:a40b9a259b52 1128
Osamu Nakamura 0:a40b9a259b52 1129
Osamu Nakamura 0:a40b9a259b52 1130 __Example__
Osamu Nakamura 0:a40b9a259b52 1131
Osamu Nakamura 0:a40b9a259b52 1132 ```js
Osamu Nakamura 0:a40b9a259b52 1133 async.applyEach([enableSearch, updateSchema], 'bucket', callback);
Osamu Nakamura 0:a40b9a259b52 1134
Osamu Nakamura 0:a40b9a259b52 1135 // partial application example:
Osamu Nakamura 0:a40b9a259b52 1136 async.each(
Osamu Nakamura 0:a40b9a259b52 1137 buckets,
Osamu Nakamura 0:a40b9a259b52 1138 async.applyEach([enableSearch, updateSchema]),
Osamu Nakamura 0:a40b9a259b52 1139 callback
Osamu Nakamura 0:a40b9a259b52 1140 );
Osamu Nakamura 0:a40b9a259b52 1141 ```
Osamu Nakamura 0:a40b9a259b52 1142
Osamu Nakamura 0:a40b9a259b52 1143 __Related__
Osamu Nakamura 0:a40b9a259b52 1144
Osamu Nakamura 0:a40b9a259b52 1145 * applyEachSeries(tasks, args..., [callback])
Osamu Nakamura 0:a40b9a259b52 1146
Osamu Nakamura 0:a40b9a259b52 1147 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1148
Osamu Nakamura 0:a40b9a259b52 1149 <a name="queue" />
Osamu Nakamura 0:a40b9a259b52 1150 ### queue(worker, [concurrency])
Osamu Nakamura 0:a40b9a259b52 1151
Osamu Nakamura 0:a40b9a259b52 1152 Creates a `queue` object with the specified `concurrency`. Tasks added to the
Osamu Nakamura 0:a40b9a259b52 1153 `queue` are processed in parallel (up to the `concurrency` limit). If all
Osamu Nakamura 0:a40b9a259b52 1154 `worker`s are in progress, the task is queued until one becomes available.
Osamu Nakamura 0:a40b9a259b52 1155 Once a `worker` completes a `task`, that `task`'s callback is called.
Osamu Nakamura 0:a40b9a259b52 1156
Osamu Nakamura 0:a40b9a259b52 1157 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1158
Osamu Nakamura 0:a40b9a259b52 1159 * `worker(task, callback)` - An asynchronous function for processing a queued
Osamu Nakamura 0:a40b9a259b52 1160 task, which must call its `callback(err)` argument when finished, with an
Osamu Nakamura 0:a40b9a259b52 1161 optional `error` as an argument. If you want to handle errors from an individual task, pass a callback to `q.push()`.
Osamu Nakamura 0:a40b9a259b52 1162 * `concurrency` - An `integer` for determining how many `worker` functions should be
Osamu Nakamura 0:a40b9a259b52 1163 run in parallel. If omitted, the concurrency defaults to `1`. If the concurrency is `0`, an error is thrown.
Osamu Nakamura 0:a40b9a259b52 1164
Osamu Nakamura 0:a40b9a259b52 1165 __Queue objects__
Osamu Nakamura 0:a40b9a259b52 1166
Osamu Nakamura 0:a40b9a259b52 1167 The `queue` object returned by this function has the following properties and
Osamu Nakamura 0:a40b9a259b52 1168 methods:
Osamu Nakamura 0:a40b9a259b52 1169
Osamu Nakamura 0:a40b9a259b52 1170 * `length()` - a function returning the number of items waiting to be processed.
Osamu Nakamura 0:a40b9a259b52 1171 * `started` - a function returning whether or not any items have been pushed and processed by the queue
Osamu Nakamura 0:a40b9a259b52 1172 * `running()` - a function returning the number of items currently being processed.
Osamu Nakamura 0:a40b9a259b52 1173 * `workersList()` - a function returning the array of items currently being processed.
Osamu Nakamura 0:a40b9a259b52 1174 * `idle()` - a function returning false if there are items waiting or being processed, or true if not.
Osamu Nakamura 0:a40b9a259b52 1175 * `concurrency` - an integer for determining how many `worker` functions should be
Osamu Nakamura 0:a40b9a259b52 1176 run in parallel. This property can be changed after a `queue` is created to
Osamu Nakamura 0:a40b9a259b52 1177 alter the concurrency on-the-fly.
Osamu Nakamura 0:a40b9a259b52 1178 * `push(task, [callback])` - add a new task to the `queue`. Calls `callback` once
Osamu Nakamura 0:a40b9a259b52 1179 the `worker` has finished processing the task. Instead of a single task, a `tasks` array
Osamu Nakamura 0:a40b9a259b52 1180 can be submitted. The respective callback is used for every task in the list.
Osamu Nakamura 0:a40b9a259b52 1181 * `unshift(task, [callback])` - add a new task to the front of the `queue`.
Osamu Nakamura 0:a40b9a259b52 1182 * `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit,
Osamu Nakamura 0:a40b9a259b52 1183 and further tasks will be queued.
Osamu Nakamura 0:a40b9a259b52 1184 * `empty` - a callback that is called when the last item from the `queue` is given to a `worker`.
Osamu Nakamura 0:a40b9a259b52 1185 * `drain` - a callback that is called when the last item from the `queue` has returned from the `worker`.
Osamu Nakamura 0:a40b9a259b52 1186 * `paused` - a boolean for determining whether the queue is in a paused state
Osamu Nakamura 0:a40b9a259b52 1187 * `pause()` - a function that pauses the processing of tasks until `resume()` is called.
Osamu Nakamura 0:a40b9a259b52 1188 * `resume()` - a function that resumes the processing of queued tasks when the queue is paused.
Osamu Nakamura 0:a40b9a259b52 1189 * `kill()` - a function that removes the `drain` callback and empties remaining tasks from the queue forcing it to go idle.
Osamu Nakamura 0:a40b9a259b52 1190
Osamu Nakamura 0:a40b9a259b52 1191 __Example__
Osamu Nakamura 0:a40b9a259b52 1192
Osamu Nakamura 0:a40b9a259b52 1193 ```js
Osamu Nakamura 0:a40b9a259b52 1194 // create a queue object with concurrency 2
Osamu Nakamura 0:a40b9a259b52 1195
Osamu Nakamura 0:a40b9a259b52 1196 var q = async.queue(function (task, callback) {
Osamu Nakamura 0:a40b9a259b52 1197 console.log('hello ' + task.name);
Osamu Nakamura 0:a40b9a259b52 1198 callback();
Osamu Nakamura 0:a40b9a259b52 1199 }, 2);
Osamu Nakamura 0:a40b9a259b52 1200
Osamu Nakamura 0:a40b9a259b52 1201
Osamu Nakamura 0:a40b9a259b52 1202 // assign a callback
Osamu Nakamura 0:a40b9a259b52 1203 q.drain = function() {
Osamu Nakamura 0:a40b9a259b52 1204 console.log('all items have been processed');
Osamu Nakamura 0:a40b9a259b52 1205 }
Osamu Nakamura 0:a40b9a259b52 1206
Osamu Nakamura 0:a40b9a259b52 1207 // add some items to the queue
Osamu Nakamura 0:a40b9a259b52 1208
Osamu Nakamura 0:a40b9a259b52 1209 q.push({name: 'foo'}, function (err) {
Osamu Nakamura 0:a40b9a259b52 1210 console.log('finished processing foo');
Osamu Nakamura 0:a40b9a259b52 1211 });
Osamu Nakamura 0:a40b9a259b52 1212 q.push({name: 'bar'}, function (err) {
Osamu Nakamura 0:a40b9a259b52 1213 console.log('finished processing bar');
Osamu Nakamura 0:a40b9a259b52 1214 });
Osamu Nakamura 0:a40b9a259b52 1215
Osamu Nakamura 0:a40b9a259b52 1216 // add some items to the queue (batch-wise)
Osamu Nakamura 0:a40b9a259b52 1217
Osamu Nakamura 0:a40b9a259b52 1218 q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {
Osamu Nakamura 0:a40b9a259b52 1219 console.log('finished processing item');
Osamu Nakamura 0:a40b9a259b52 1220 });
Osamu Nakamura 0:a40b9a259b52 1221
Osamu Nakamura 0:a40b9a259b52 1222 // add some items to the front of the queue
Osamu Nakamura 0:a40b9a259b52 1223
Osamu Nakamura 0:a40b9a259b52 1224 q.unshift({name: 'bar'}, function (err) {
Osamu Nakamura 0:a40b9a259b52 1225 console.log('finished processing bar');
Osamu Nakamura 0:a40b9a259b52 1226 });
Osamu Nakamura 0:a40b9a259b52 1227 ```
Osamu Nakamura 0:a40b9a259b52 1228
Osamu Nakamura 0:a40b9a259b52 1229
Osamu Nakamura 0:a40b9a259b52 1230 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1231
Osamu Nakamura 0:a40b9a259b52 1232 <a name="priorityQueue" />
Osamu Nakamura 0:a40b9a259b52 1233 ### priorityQueue(worker, concurrency)
Osamu Nakamura 0:a40b9a259b52 1234
Osamu Nakamura 0:a40b9a259b52 1235 The same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects:
Osamu Nakamura 0:a40b9a259b52 1236
Osamu Nakamura 0:a40b9a259b52 1237 * `push(task, priority, [callback])` - `priority` should be a number. If an array of
Osamu Nakamura 0:a40b9a259b52 1238 `tasks` is given, all tasks will be assigned the same priority.
Osamu Nakamura 0:a40b9a259b52 1239 * The `unshift` method was removed.
Osamu Nakamura 0:a40b9a259b52 1240
Osamu Nakamura 0:a40b9a259b52 1241 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1242
Osamu Nakamura 0:a40b9a259b52 1243 <a name="cargo" />
Osamu Nakamura 0:a40b9a259b52 1244 ### cargo(worker, [payload])
Osamu Nakamura 0:a40b9a259b52 1245
Osamu Nakamura 0:a40b9a259b52 1246 Creates a `cargo` object with the specified payload. Tasks added to the
Osamu Nakamura 0:a40b9a259b52 1247 cargo will be processed altogether (up to the `payload` limit). If the
Osamu Nakamura 0:a40b9a259b52 1248 `worker` is in progress, the task is queued until it becomes available. Once
Osamu Nakamura 0:a40b9a259b52 1249 the `worker` has completed some tasks, each callback of those tasks is called.
Osamu Nakamura 0:a40b9a259b52 1250 Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966) for how `cargo` and `queue` work.
Osamu Nakamura 0:a40b9a259b52 1251
Osamu Nakamura 0:a40b9a259b52 1252 While [queue](#queue) passes only one task to one of a group of workers
Osamu Nakamura 0:a40b9a259b52 1253 at a time, cargo passes an array of tasks to a single worker, repeating
Osamu Nakamura 0:a40b9a259b52 1254 when the worker is finished.
Osamu Nakamura 0:a40b9a259b52 1255
Osamu Nakamura 0:a40b9a259b52 1256 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1257
Osamu Nakamura 0:a40b9a259b52 1258 * `worker(tasks, callback)` - An asynchronous function for processing an array of
Osamu Nakamura 0:a40b9a259b52 1259 queued tasks, which must call its `callback(err)` argument when finished, with
Osamu Nakamura 0:a40b9a259b52 1260 an optional `err` argument.
Osamu Nakamura 0:a40b9a259b52 1261 * `payload` - An optional `integer` for determining how many tasks should be
Osamu Nakamura 0:a40b9a259b52 1262 processed per round; if omitted, the default is unlimited.
Osamu Nakamura 0:a40b9a259b52 1263
Osamu Nakamura 0:a40b9a259b52 1264 __Cargo objects__
Osamu Nakamura 0:a40b9a259b52 1265
Osamu Nakamura 0:a40b9a259b52 1266 The `cargo` object returned by this function has the following properties and
Osamu Nakamura 0:a40b9a259b52 1267 methods:
Osamu Nakamura 0:a40b9a259b52 1268
Osamu Nakamura 0:a40b9a259b52 1269 * `length()` - A function returning the number of items waiting to be processed.
Osamu Nakamura 0:a40b9a259b52 1270 * `payload` - An `integer` for determining how many tasks should be
Osamu Nakamura 0:a40b9a259b52 1271 process per round. This property can be changed after a `cargo` is created to
Osamu Nakamura 0:a40b9a259b52 1272 alter the payload on-the-fly.
Osamu Nakamura 0:a40b9a259b52 1273 * `push(task, [callback])` - Adds `task` to the `queue`. The callback is called
Osamu Nakamura 0:a40b9a259b52 1274 once the `worker` has finished processing the task. Instead of a single task, an array of `tasks`
Osamu Nakamura 0:a40b9a259b52 1275 can be submitted. The respective callback is used for every task in the list.
Osamu Nakamura 0:a40b9a259b52 1276 * `saturated` - A callback that is called when the `queue.length()` hits the concurrency and further tasks will be queued.
Osamu Nakamura 0:a40b9a259b52 1277 * `empty` - A callback that is called when the last item from the `queue` is given to a `worker`.
Osamu Nakamura 0:a40b9a259b52 1278 * `drain` - A callback that is called when the last item from the `queue` has returned from the `worker`.
Osamu Nakamura 0:a40b9a259b52 1279 * `idle()`, `pause()`, `resume()`, `kill()` - cargo inherits all of the same methods and event calbacks as [`queue`](#queue)
Osamu Nakamura 0:a40b9a259b52 1280
Osamu Nakamura 0:a40b9a259b52 1281 __Example__
Osamu Nakamura 0:a40b9a259b52 1282
Osamu Nakamura 0:a40b9a259b52 1283 ```js
Osamu Nakamura 0:a40b9a259b52 1284 // create a cargo object with payload 2
Osamu Nakamura 0:a40b9a259b52 1285
Osamu Nakamura 0:a40b9a259b52 1286 var cargo = async.cargo(function (tasks, callback) {
Osamu Nakamura 0:a40b9a259b52 1287 for(var i=0; i<tasks.length; i++){
Osamu Nakamura 0:a40b9a259b52 1288 console.log('hello ' + tasks[i].name);
Osamu Nakamura 0:a40b9a259b52 1289 }
Osamu Nakamura 0:a40b9a259b52 1290 callback();
Osamu Nakamura 0:a40b9a259b52 1291 }, 2);
Osamu Nakamura 0:a40b9a259b52 1292
Osamu Nakamura 0:a40b9a259b52 1293
Osamu Nakamura 0:a40b9a259b52 1294 // add some items
Osamu Nakamura 0:a40b9a259b52 1295
Osamu Nakamura 0:a40b9a259b52 1296 cargo.push({name: 'foo'}, function (err) {
Osamu Nakamura 0:a40b9a259b52 1297 console.log('finished processing foo');
Osamu Nakamura 0:a40b9a259b52 1298 });
Osamu Nakamura 0:a40b9a259b52 1299 cargo.push({name: 'bar'}, function (err) {
Osamu Nakamura 0:a40b9a259b52 1300 console.log('finished processing bar');
Osamu Nakamura 0:a40b9a259b52 1301 });
Osamu Nakamura 0:a40b9a259b52 1302 cargo.push({name: 'baz'}, function (err) {
Osamu Nakamura 0:a40b9a259b52 1303 console.log('finished processing baz');
Osamu Nakamura 0:a40b9a259b52 1304 });
Osamu Nakamura 0:a40b9a259b52 1305 ```
Osamu Nakamura 0:a40b9a259b52 1306
Osamu Nakamura 0:a40b9a259b52 1307 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1308
Osamu Nakamura 0:a40b9a259b52 1309 <a name="auto" />
Osamu Nakamura 0:a40b9a259b52 1310 ### auto(tasks, [concurrency], [callback])
Osamu Nakamura 0:a40b9a259b52 1311
Osamu Nakamura 0:a40b9a259b52 1312 Determines the best order for running the functions in `tasks`, based on their requirements. Each function can optionally depend on other functions being completed first, and each function is run as soon as its requirements are satisfied.
Osamu Nakamura 0:a40b9a259b52 1313
Osamu Nakamura 0:a40b9a259b52 1314 If any of the functions pass an error to their callback, the `auto` sequence will stop. Further tasks will not execute (so any other functions depending on it will not run), and the main `callback` is immediately called with the error. Functions also receive an object containing the results of functions which have completed so far.
Osamu Nakamura 0:a40b9a259b52 1315
Osamu Nakamura 0:a40b9a259b52 1316 Note, all functions are called with a `results` object as a second argument,
Osamu Nakamura 0:a40b9a259b52 1317 so it is unsafe to pass functions in the `tasks` object which cannot handle the
Osamu Nakamura 0:a40b9a259b52 1318 extra argument.
Osamu Nakamura 0:a40b9a259b52 1319
Osamu Nakamura 0:a40b9a259b52 1320 For example, this snippet of code:
Osamu Nakamura 0:a40b9a259b52 1321
Osamu Nakamura 0:a40b9a259b52 1322 ```js
Osamu Nakamura 0:a40b9a259b52 1323 async.auto({
Osamu Nakamura 0:a40b9a259b52 1324 readData: async.apply(fs.readFile, 'data.txt', 'utf-8')
Osamu Nakamura 0:a40b9a259b52 1325 }, callback);
Osamu Nakamura 0:a40b9a259b52 1326 ```
Osamu Nakamura 0:a40b9a259b52 1327
Osamu Nakamura 0:a40b9a259b52 1328 will have the effect of calling `readFile` with the results object as the last
Osamu Nakamura 0:a40b9a259b52 1329 argument, which will fail:
Osamu Nakamura 0:a40b9a259b52 1330
Osamu Nakamura 0:a40b9a259b52 1331 ```js
Osamu Nakamura 0:a40b9a259b52 1332 fs.readFile('data.txt', 'utf-8', cb, {});
Osamu Nakamura 0:a40b9a259b52 1333 ```
Osamu Nakamura 0:a40b9a259b52 1334
Osamu Nakamura 0:a40b9a259b52 1335 Instead, wrap the call to `readFile` in a function which does not forward the
Osamu Nakamura 0:a40b9a259b52 1336 `results` object:
Osamu Nakamura 0:a40b9a259b52 1337
Osamu Nakamura 0:a40b9a259b52 1338 ```js
Osamu Nakamura 0:a40b9a259b52 1339 async.auto({
Osamu Nakamura 0:a40b9a259b52 1340 readData: function(cb, results){
Osamu Nakamura 0:a40b9a259b52 1341 fs.readFile('data.txt', 'utf-8', cb);
Osamu Nakamura 0:a40b9a259b52 1342 }
Osamu Nakamura 0:a40b9a259b52 1343 }, callback);
Osamu Nakamura 0:a40b9a259b52 1344 ```
Osamu Nakamura 0:a40b9a259b52 1345
Osamu Nakamura 0:a40b9a259b52 1346 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1347
Osamu Nakamura 0:a40b9a259b52 1348 * `tasks` - An object. Each of its properties is either a function or an array of
Osamu Nakamura 0:a40b9a259b52 1349 requirements, with the function itself the last item in the array. The object's key
Osamu Nakamura 0:a40b9a259b52 1350 of a property serves as the name of the task defined by that property,
Osamu Nakamura 0:a40b9a259b52 1351 i.e. can be used when specifying requirements for other tasks.
Osamu Nakamura 0:a40b9a259b52 1352 The function receives two arguments: (1) a `callback(err, result)` which must be
Osamu Nakamura 0:a40b9a259b52 1353 called when finished, passing an `error` (which can be `null`) and the result of
Osamu Nakamura 0:a40b9a259b52 1354 the function's execution, and (2) a `results` object, containing the results of
Osamu Nakamura 0:a40b9a259b52 1355 the previously executed functions.
Osamu Nakamura 0:a40b9a259b52 1356 * `concurrency` - An optional `integer` for determining the maximum number of tasks that can be run in parallel. By default, as many as possible.
Osamu Nakamura 0:a40b9a259b52 1357 * `callback(err, results)` - An optional callback which is called when all the
Osamu Nakamura 0:a40b9a259b52 1358 tasks have been completed. It receives the `err` argument if any `tasks`
Osamu Nakamura 0:a40b9a259b52 1359 pass an error to their callback. Results are always returned; however, if
Osamu Nakamura 0:a40b9a259b52 1360 an error occurs, no further `tasks` will be performed, and the results
Osamu Nakamura 0:a40b9a259b52 1361 object will only contain partial results.
Osamu Nakamura 0:a40b9a259b52 1362
Osamu Nakamura 0:a40b9a259b52 1363
Osamu Nakamura 0:a40b9a259b52 1364 __Example__
Osamu Nakamura 0:a40b9a259b52 1365
Osamu Nakamura 0:a40b9a259b52 1366 ```js
Osamu Nakamura 0:a40b9a259b52 1367 async.auto({
Osamu Nakamura 0:a40b9a259b52 1368 get_data: function(callback){
Osamu Nakamura 0:a40b9a259b52 1369 console.log('in get_data');
Osamu Nakamura 0:a40b9a259b52 1370 // async code to get some data
Osamu Nakamura 0:a40b9a259b52 1371 callback(null, 'data', 'converted to array');
Osamu Nakamura 0:a40b9a259b52 1372 },
Osamu Nakamura 0:a40b9a259b52 1373 make_folder: function(callback){
Osamu Nakamura 0:a40b9a259b52 1374 console.log('in make_folder');
Osamu Nakamura 0:a40b9a259b52 1375 // async code to create a directory to store a file in
Osamu Nakamura 0:a40b9a259b52 1376 // this is run at the same time as getting the data
Osamu Nakamura 0:a40b9a259b52 1377 callback(null, 'folder');
Osamu Nakamura 0:a40b9a259b52 1378 },
Osamu Nakamura 0:a40b9a259b52 1379 write_file: ['get_data', 'make_folder', function(callback, results){
Osamu Nakamura 0:a40b9a259b52 1380 console.log('in write_file', JSON.stringify(results));
Osamu Nakamura 0:a40b9a259b52 1381 // once there is some data and the directory exists,
Osamu Nakamura 0:a40b9a259b52 1382 // write the data to a file in the directory
Osamu Nakamura 0:a40b9a259b52 1383 callback(null, 'filename');
Osamu Nakamura 0:a40b9a259b52 1384 }],
Osamu Nakamura 0:a40b9a259b52 1385 email_link: ['write_file', function(callback, results){
Osamu Nakamura 0:a40b9a259b52 1386 console.log('in email_link', JSON.stringify(results));
Osamu Nakamura 0:a40b9a259b52 1387 // once the file is written let's email a link to it...
Osamu Nakamura 0:a40b9a259b52 1388 // results.write_file contains the filename returned by write_file.
Osamu Nakamura 0:a40b9a259b52 1389 callback(null, {'file':results.write_file, 'email':'user@example.com'});
Osamu Nakamura 0:a40b9a259b52 1390 }]
Osamu Nakamura 0:a40b9a259b52 1391 }, function(err, results) {
Osamu Nakamura 0:a40b9a259b52 1392 console.log('err = ', err);
Osamu Nakamura 0:a40b9a259b52 1393 console.log('results = ', results);
Osamu Nakamura 0:a40b9a259b52 1394 });
Osamu Nakamura 0:a40b9a259b52 1395 ```
Osamu Nakamura 0:a40b9a259b52 1396
Osamu Nakamura 0:a40b9a259b52 1397 This is a fairly trivial example, but to do this using the basic parallel and
Osamu Nakamura 0:a40b9a259b52 1398 series functions would look like this:
Osamu Nakamura 0:a40b9a259b52 1399
Osamu Nakamura 0:a40b9a259b52 1400 ```js
Osamu Nakamura 0:a40b9a259b52 1401 async.parallel([
Osamu Nakamura 0:a40b9a259b52 1402 function(callback){
Osamu Nakamura 0:a40b9a259b52 1403 console.log('in get_data');
Osamu Nakamura 0:a40b9a259b52 1404 // async code to get some data
Osamu Nakamura 0:a40b9a259b52 1405 callback(null, 'data', 'converted to array');
Osamu Nakamura 0:a40b9a259b52 1406 },
Osamu Nakamura 0:a40b9a259b52 1407 function(callback){
Osamu Nakamura 0:a40b9a259b52 1408 console.log('in make_folder');
Osamu Nakamura 0:a40b9a259b52 1409 // async code to create a directory to store a file in
Osamu Nakamura 0:a40b9a259b52 1410 // this is run at the same time as getting the data
Osamu Nakamura 0:a40b9a259b52 1411 callback(null, 'folder');
Osamu Nakamura 0:a40b9a259b52 1412 }
Osamu Nakamura 0:a40b9a259b52 1413 ],
Osamu Nakamura 0:a40b9a259b52 1414 function(err, results){
Osamu Nakamura 0:a40b9a259b52 1415 async.series([
Osamu Nakamura 0:a40b9a259b52 1416 function(callback){
Osamu Nakamura 0:a40b9a259b52 1417 console.log('in write_file', JSON.stringify(results));
Osamu Nakamura 0:a40b9a259b52 1418 // once there is some data and the directory exists,
Osamu Nakamura 0:a40b9a259b52 1419 // write the data to a file in the directory
Osamu Nakamura 0:a40b9a259b52 1420 results.push('filename');
Osamu Nakamura 0:a40b9a259b52 1421 callback(null);
Osamu Nakamura 0:a40b9a259b52 1422 },
Osamu Nakamura 0:a40b9a259b52 1423 function(callback){
Osamu Nakamura 0:a40b9a259b52 1424 console.log('in email_link', JSON.stringify(results));
Osamu Nakamura 0:a40b9a259b52 1425 // once the file is written let's email a link to it...
Osamu Nakamura 0:a40b9a259b52 1426 callback(null, {'file':results.pop(), 'email':'user@example.com'});
Osamu Nakamura 0:a40b9a259b52 1427 }
Osamu Nakamura 0:a40b9a259b52 1428 ]);
Osamu Nakamura 0:a40b9a259b52 1429 });
Osamu Nakamura 0:a40b9a259b52 1430 ```
Osamu Nakamura 0:a40b9a259b52 1431
Osamu Nakamura 0:a40b9a259b52 1432 For a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding
Osamu Nakamura 0:a40b9a259b52 1433 new tasks much easier (and the code more readable).
Osamu Nakamura 0:a40b9a259b52 1434
Osamu Nakamura 0:a40b9a259b52 1435
Osamu Nakamura 0:a40b9a259b52 1436 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1437
Osamu Nakamura 0:a40b9a259b52 1438 <a name="retry" />
Osamu Nakamura 0:a40b9a259b52 1439 ### retry([opts = {times: 5, interval: 0}| 5], task, [callback])
Osamu Nakamura 0:a40b9a259b52 1440
Osamu Nakamura 0:a40b9a259b52 1441 Attempts to get a successful response from `task` no more than `times` times before
Osamu Nakamura 0:a40b9a259b52 1442 returning an error. If the task is successful, the `callback` will be passed the result
Osamu Nakamura 0:a40b9a259b52 1443 of the successful task. If all attempts fail, the callback will be passed the error and
Osamu Nakamura 0:a40b9a259b52 1444 result (if any) of the final attempt.
Osamu Nakamura 0:a40b9a259b52 1445
Osamu Nakamura 0:a40b9a259b52 1446 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1447
Osamu Nakamura 0:a40b9a259b52 1448 * `opts` - Can be either an object with `times` and `interval` or a number.
Osamu Nakamura 0:a40b9a259b52 1449 * `times` - The number of attempts to make before giving up. The default is `5`.
Osamu Nakamura 0:a40b9a259b52 1450 * `interval` - The time to wait between retries, in milliseconds. The default is `0`.
Osamu Nakamura 0:a40b9a259b52 1451 * If `opts` is a number, the number specifies the number of times to retry, with the default interval of `0`.
Osamu Nakamura 0:a40b9a259b52 1452 * `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)`
Osamu Nakamura 0:a40b9a259b52 1453 which must be called when finished, passing `err` (which can be `null`) and the `result` of
Osamu Nakamura 0:a40b9a259b52 1454 the function's execution, and (2) a `results` object, containing the results of
Osamu Nakamura 0:a40b9a259b52 1455 the previously executed functions (if nested inside another control flow).
Osamu Nakamura 0:a40b9a259b52 1456 * `callback(err, results)` - An optional callback which is called when the
Osamu Nakamura 0:a40b9a259b52 1457 task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`.
Osamu Nakamura 0:a40b9a259b52 1458
Osamu Nakamura 0:a40b9a259b52 1459 The [`retry`](#retry) function can be used as a stand-alone control flow by passing a callback, as shown below:
Osamu Nakamura 0:a40b9a259b52 1460
Osamu Nakamura 0:a40b9a259b52 1461 ```js
Osamu Nakamura 0:a40b9a259b52 1462 // try calling apiMethod 3 times
Osamu Nakamura 0:a40b9a259b52 1463 async.retry(3, apiMethod, function(err, result) {
Osamu Nakamura 0:a40b9a259b52 1464 // do something with the result
Osamu Nakamura 0:a40b9a259b52 1465 });
Osamu Nakamura 0:a40b9a259b52 1466 ```
Osamu Nakamura 0:a40b9a259b52 1467
Osamu Nakamura 0:a40b9a259b52 1468 ```js
Osamu Nakamura 0:a40b9a259b52 1469 // try calling apiMethod 3 times, waiting 200 ms between each retry
Osamu Nakamura 0:a40b9a259b52 1470 async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
Osamu Nakamura 0:a40b9a259b52 1471 // do something with the result
Osamu Nakamura 0:a40b9a259b52 1472 });
Osamu Nakamura 0:a40b9a259b52 1473 ```
Osamu Nakamura 0:a40b9a259b52 1474
Osamu Nakamura 0:a40b9a259b52 1475 ```js
Osamu Nakamura 0:a40b9a259b52 1476 // try calling apiMethod the default 5 times no delay between each retry
Osamu Nakamura 0:a40b9a259b52 1477 async.retry(apiMethod, function(err, result) {
Osamu Nakamura 0:a40b9a259b52 1478 // do something with the result
Osamu Nakamura 0:a40b9a259b52 1479 });
Osamu Nakamura 0:a40b9a259b52 1480 ```
Osamu Nakamura 0:a40b9a259b52 1481
Osamu Nakamura 0:a40b9a259b52 1482 It can also be embedded within other control flow functions to retry individual methods
Osamu Nakamura 0:a40b9a259b52 1483 that are not as reliable, like this:
Osamu Nakamura 0:a40b9a259b52 1484
Osamu Nakamura 0:a40b9a259b52 1485 ```js
Osamu Nakamura 0:a40b9a259b52 1486 async.auto({
Osamu Nakamura 0:a40b9a259b52 1487 users: api.getUsers.bind(api),
Osamu Nakamura 0:a40b9a259b52 1488 payments: async.retry(3, api.getPayments.bind(api))
Osamu Nakamura 0:a40b9a259b52 1489 }, function(err, results) {
Osamu Nakamura 0:a40b9a259b52 1490 // do something with the results
Osamu Nakamura 0:a40b9a259b52 1491 });
Osamu Nakamura 0:a40b9a259b52 1492 ```
Osamu Nakamura 0:a40b9a259b52 1493
Osamu Nakamura 0:a40b9a259b52 1494
Osamu Nakamura 0:a40b9a259b52 1495 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1496
Osamu Nakamura 0:a40b9a259b52 1497 <a name="iterator" />
Osamu Nakamura 0:a40b9a259b52 1498 ### iterator(tasks)
Osamu Nakamura 0:a40b9a259b52 1499
Osamu Nakamura 0:a40b9a259b52 1500 Creates an iterator function which calls the next function in the `tasks` array,
Osamu Nakamura 0:a40b9a259b52 1501 returning a continuation to call the next one after that. It's also possible to
Osamu Nakamura 0:a40b9a259b52 1502 “peek” at the next iterator with `iterator.next()`.
Osamu Nakamura 0:a40b9a259b52 1503
Osamu Nakamura 0:a40b9a259b52 1504 This function is used internally by the `async` module, but can be useful when
Osamu Nakamura 0:a40b9a259b52 1505 you want to manually control the flow of functions in series.
Osamu Nakamura 0:a40b9a259b52 1506
Osamu Nakamura 0:a40b9a259b52 1507 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1508
Osamu Nakamura 0:a40b9a259b52 1509 * `tasks` - An array of functions to run.
Osamu Nakamura 0:a40b9a259b52 1510
Osamu Nakamura 0:a40b9a259b52 1511 __Example__
Osamu Nakamura 0:a40b9a259b52 1512
Osamu Nakamura 0:a40b9a259b52 1513 ```js
Osamu Nakamura 0:a40b9a259b52 1514 var iterator = async.iterator([
Osamu Nakamura 0:a40b9a259b52 1515 function(){ sys.p('one'); },
Osamu Nakamura 0:a40b9a259b52 1516 function(){ sys.p('two'); },
Osamu Nakamura 0:a40b9a259b52 1517 function(){ sys.p('three'); }
Osamu Nakamura 0:a40b9a259b52 1518 ]);
Osamu Nakamura 0:a40b9a259b52 1519
Osamu Nakamura 0:a40b9a259b52 1520 node> var iterator2 = iterator();
Osamu Nakamura 0:a40b9a259b52 1521 'one'
Osamu Nakamura 0:a40b9a259b52 1522 node> var iterator3 = iterator2();
Osamu Nakamura 0:a40b9a259b52 1523 'two'
Osamu Nakamura 0:a40b9a259b52 1524 node> iterator3();
Osamu Nakamura 0:a40b9a259b52 1525 'three'
Osamu Nakamura 0:a40b9a259b52 1526 node> var nextfn = iterator2.next();
Osamu Nakamura 0:a40b9a259b52 1527 node> nextfn();
Osamu Nakamura 0:a40b9a259b52 1528 'three'
Osamu Nakamura 0:a40b9a259b52 1529 ```
Osamu Nakamura 0:a40b9a259b52 1530
Osamu Nakamura 0:a40b9a259b52 1531 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1532
Osamu Nakamura 0:a40b9a259b52 1533 <a name="apply" />
Osamu Nakamura 0:a40b9a259b52 1534 ### apply(function, arguments..)
Osamu Nakamura 0:a40b9a259b52 1535
Osamu Nakamura 0:a40b9a259b52 1536 Creates a continuation function with some arguments already applied.
Osamu Nakamura 0:a40b9a259b52 1537
Osamu Nakamura 0:a40b9a259b52 1538 Useful as a shorthand when combined with other control flow functions. Any arguments
Osamu Nakamura 0:a40b9a259b52 1539 passed to the returned function are added to the arguments originally passed
Osamu Nakamura 0:a40b9a259b52 1540 to apply.
Osamu Nakamura 0:a40b9a259b52 1541
Osamu Nakamura 0:a40b9a259b52 1542 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1543
Osamu Nakamura 0:a40b9a259b52 1544 * `function` - The function you want to eventually apply all arguments to.
Osamu Nakamura 0:a40b9a259b52 1545 * `arguments...` - Any number of arguments to automatically apply when the
Osamu Nakamura 0:a40b9a259b52 1546 continuation is called.
Osamu Nakamura 0:a40b9a259b52 1547
Osamu Nakamura 0:a40b9a259b52 1548 __Example__
Osamu Nakamura 0:a40b9a259b52 1549
Osamu Nakamura 0:a40b9a259b52 1550 ```js
Osamu Nakamura 0:a40b9a259b52 1551 // using apply
Osamu Nakamura 0:a40b9a259b52 1552
Osamu Nakamura 0:a40b9a259b52 1553 async.parallel([
Osamu Nakamura 0:a40b9a259b52 1554 async.apply(fs.writeFile, 'testfile1', 'test1'),
Osamu Nakamura 0:a40b9a259b52 1555 async.apply(fs.writeFile, 'testfile2', 'test2'),
Osamu Nakamura 0:a40b9a259b52 1556 ]);
Osamu Nakamura 0:a40b9a259b52 1557
Osamu Nakamura 0:a40b9a259b52 1558
Osamu Nakamura 0:a40b9a259b52 1559 // the same process without using apply
Osamu Nakamura 0:a40b9a259b52 1560
Osamu Nakamura 0:a40b9a259b52 1561 async.parallel([
Osamu Nakamura 0:a40b9a259b52 1562 function(callback){
Osamu Nakamura 0:a40b9a259b52 1563 fs.writeFile('testfile1', 'test1', callback);
Osamu Nakamura 0:a40b9a259b52 1564 },
Osamu Nakamura 0:a40b9a259b52 1565 function(callback){
Osamu Nakamura 0:a40b9a259b52 1566 fs.writeFile('testfile2', 'test2', callback);
Osamu Nakamura 0:a40b9a259b52 1567 }
Osamu Nakamura 0:a40b9a259b52 1568 ]);
Osamu Nakamura 0:a40b9a259b52 1569 ```
Osamu Nakamura 0:a40b9a259b52 1570
Osamu Nakamura 0:a40b9a259b52 1571 It's possible to pass any number of additional arguments when calling the
Osamu Nakamura 0:a40b9a259b52 1572 continuation:
Osamu Nakamura 0:a40b9a259b52 1573
Osamu Nakamura 0:a40b9a259b52 1574 ```js
Osamu Nakamura 0:a40b9a259b52 1575 node> var fn = async.apply(sys.puts, 'one');
Osamu Nakamura 0:a40b9a259b52 1576 node> fn('two', 'three');
Osamu Nakamura 0:a40b9a259b52 1577 one
Osamu Nakamura 0:a40b9a259b52 1578 two
Osamu Nakamura 0:a40b9a259b52 1579 three
Osamu Nakamura 0:a40b9a259b52 1580 ```
Osamu Nakamura 0:a40b9a259b52 1581
Osamu Nakamura 0:a40b9a259b52 1582 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1583
Osamu Nakamura 0:a40b9a259b52 1584 <a name="nextTick" />
Osamu Nakamura 0:a40b9a259b52 1585 ### nextTick(callback), setImmediate(callback)
Osamu Nakamura 0:a40b9a259b52 1586
Osamu Nakamura 0:a40b9a259b52 1587 Calls `callback` on a later loop around the event loop. In Node.js this just
Osamu Nakamura 0:a40b9a259b52 1588 calls `process.nextTick`; in the browser it falls back to `setImmediate(callback)`
Osamu Nakamura 0:a40b9a259b52 1589 if available, otherwise `setTimeout(callback, 0)`, which means other higher priority
Osamu Nakamura 0:a40b9a259b52 1590 events may precede the execution of `callback`.
Osamu Nakamura 0:a40b9a259b52 1591
Osamu Nakamura 0:a40b9a259b52 1592 This is used internally for browser-compatibility purposes.
Osamu Nakamura 0:a40b9a259b52 1593
Osamu Nakamura 0:a40b9a259b52 1594 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1595
Osamu Nakamura 0:a40b9a259b52 1596 * `callback` - The function to call on a later loop around the event loop.
Osamu Nakamura 0:a40b9a259b52 1597
Osamu Nakamura 0:a40b9a259b52 1598 __Example__
Osamu Nakamura 0:a40b9a259b52 1599
Osamu Nakamura 0:a40b9a259b52 1600 ```js
Osamu Nakamura 0:a40b9a259b52 1601 var call_order = [];
Osamu Nakamura 0:a40b9a259b52 1602 async.nextTick(function(){
Osamu Nakamura 0:a40b9a259b52 1603 call_order.push('two');
Osamu Nakamura 0:a40b9a259b52 1604 // call_order now equals ['one','two']
Osamu Nakamura 0:a40b9a259b52 1605 });
Osamu Nakamura 0:a40b9a259b52 1606 call_order.push('one')
Osamu Nakamura 0:a40b9a259b52 1607 ```
Osamu Nakamura 0:a40b9a259b52 1608
Osamu Nakamura 0:a40b9a259b52 1609 <a name="times" />
Osamu Nakamura 0:a40b9a259b52 1610 ### times(n, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 1611
Osamu Nakamura 0:a40b9a259b52 1612 Calls the `iterator` function `n` times, and accumulates results in the same manner
Osamu Nakamura 0:a40b9a259b52 1613 you would use with [`map`](#map).
Osamu Nakamura 0:a40b9a259b52 1614
Osamu Nakamura 0:a40b9a259b52 1615 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1616
Osamu Nakamura 0:a40b9a259b52 1617 * `n` - The number of times to run the function.
Osamu Nakamura 0:a40b9a259b52 1618 * `iterator` - The function to call `n` times.
Osamu Nakamura 0:a40b9a259b52 1619 * `callback` - see [`map`](#map)
Osamu Nakamura 0:a40b9a259b52 1620
Osamu Nakamura 0:a40b9a259b52 1621 __Example__
Osamu Nakamura 0:a40b9a259b52 1622
Osamu Nakamura 0:a40b9a259b52 1623 ```js
Osamu Nakamura 0:a40b9a259b52 1624 // Pretend this is some complicated async factory
Osamu Nakamura 0:a40b9a259b52 1625 var createUser = function(id, callback) {
Osamu Nakamura 0:a40b9a259b52 1626 callback(null, {
Osamu Nakamura 0:a40b9a259b52 1627 id: 'user' + id
Osamu Nakamura 0:a40b9a259b52 1628 })
Osamu Nakamura 0:a40b9a259b52 1629 }
Osamu Nakamura 0:a40b9a259b52 1630 // generate 5 users
Osamu Nakamura 0:a40b9a259b52 1631 async.times(5, function(n, next){
Osamu Nakamura 0:a40b9a259b52 1632 createUser(n, function(err, user) {
Osamu Nakamura 0:a40b9a259b52 1633 next(err, user)
Osamu Nakamura 0:a40b9a259b52 1634 })
Osamu Nakamura 0:a40b9a259b52 1635 }, function(err, users) {
Osamu Nakamura 0:a40b9a259b52 1636 // we should now have 5 users
Osamu Nakamura 0:a40b9a259b52 1637 });
Osamu Nakamura 0:a40b9a259b52 1638 ```
Osamu Nakamura 0:a40b9a259b52 1639
Osamu Nakamura 0:a40b9a259b52 1640 __Related__
Osamu Nakamura 0:a40b9a259b52 1641
Osamu Nakamura 0:a40b9a259b52 1642 * timesSeries(n, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 1643 * timesLimit(n, limit, iterator, [callback])
Osamu Nakamura 0:a40b9a259b52 1644
Osamu Nakamura 0:a40b9a259b52 1645
Osamu Nakamura 0:a40b9a259b52 1646 ## Utils
Osamu Nakamura 0:a40b9a259b52 1647
Osamu Nakamura 0:a40b9a259b52 1648 <a name="memoize" />
Osamu Nakamura 0:a40b9a259b52 1649 ### memoize(fn, [hasher])
Osamu Nakamura 0:a40b9a259b52 1650
Osamu Nakamura 0:a40b9a259b52 1651 Caches the results of an `async` function. When creating a hash to store function
Osamu Nakamura 0:a40b9a259b52 1652 results against, the callback is omitted from the hash and an optional hash
Osamu Nakamura 0:a40b9a259b52 1653 function can be used.
Osamu Nakamura 0:a40b9a259b52 1654
Osamu Nakamura 0:a40b9a259b52 1655 If no hash function is specified, the first argument is used as a hash key, which may work reasonably if it is a string or a data type that converts to a distinct string. Note that objects and arrays will not behave reasonably. Neither will cases where the other arguments are significant. In such cases, specify your own hash function.
Osamu Nakamura 0:a40b9a259b52 1656
Osamu Nakamura 0:a40b9a259b52 1657 The cache of results is exposed as the `memo` property of the function returned
Osamu Nakamura 0:a40b9a259b52 1658 by `memoize`.
Osamu Nakamura 0:a40b9a259b52 1659
Osamu Nakamura 0:a40b9a259b52 1660 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1661
Osamu Nakamura 0:a40b9a259b52 1662 * `fn` - The function to proxy and cache results from.
Osamu Nakamura 0:a40b9a259b52 1663 * `hasher` - An optional function for generating a custom hash for storing
Osamu Nakamura 0:a40b9a259b52 1664 results. It has all the arguments applied to it apart from the callback, and
Osamu Nakamura 0:a40b9a259b52 1665 must be synchronous.
Osamu Nakamura 0:a40b9a259b52 1666
Osamu Nakamura 0:a40b9a259b52 1667 __Example__
Osamu Nakamura 0:a40b9a259b52 1668
Osamu Nakamura 0:a40b9a259b52 1669 ```js
Osamu Nakamura 0:a40b9a259b52 1670 var slow_fn = function (name, callback) {
Osamu Nakamura 0:a40b9a259b52 1671 // do something
Osamu Nakamura 0:a40b9a259b52 1672 callback(null, result);
Osamu Nakamura 0:a40b9a259b52 1673 };
Osamu Nakamura 0:a40b9a259b52 1674 var fn = async.memoize(slow_fn);
Osamu Nakamura 0:a40b9a259b52 1675
Osamu Nakamura 0:a40b9a259b52 1676 // fn can now be used as if it were slow_fn
Osamu Nakamura 0:a40b9a259b52 1677 fn('some name', function () {
Osamu Nakamura 0:a40b9a259b52 1678 // callback
Osamu Nakamura 0:a40b9a259b52 1679 });
Osamu Nakamura 0:a40b9a259b52 1680 ```
Osamu Nakamura 0:a40b9a259b52 1681
Osamu Nakamura 0:a40b9a259b52 1682 <a name="unmemoize" />
Osamu Nakamura 0:a40b9a259b52 1683 ### unmemoize(fn)
Osamu Nakamura 0:a40b9a259b52 1684
Osamu Nakamura 0:a40b9a259b52 1685 Undoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized
Osamu Nakamura 0:a40b9a259b52 1686 form. Handy for testing.
Osamu Nakamura 0:a40b9a259b52 1687
Osamu Nakamura 0:a40b9a259b52 1688 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1689
Osamu Nakamura 0:a40b9a259b52 1690 * `fn` - the memoized function
Osamu Nakamura 0:a40b9a259b52 1691
Osamu Nakamura 0:a40b9a259b52 1692 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1693
Osamu Nakamura 0:a40b9a259b52 1694 <a name="ensureAsync" />
Osamu Nakamura 0:a40b9a259b52 1695 ### ensureAsync(fn)
Osamu Nakamura 0:a40b9a259b52 1696
Osamu Nakamura 0:a40b9a259b52 1697 Wrap an async function and ensure it calls its callback on a later tick of the event loop. If the function already calls its callback on a next tick, no extra deferral is added. This is useful for preventing stack overflows (`RangeError: Maximum call stack size exceeded`) and generally keeping [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) contained.
Osamu Nakamura 0:a40b9a259b52 1698
Osamu Nakamura 0:a40b9a259b52 1699 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1700
Osamu Nakamura 0:a40b9a259b52 1701 * `fn` - an async function, one that expects a node-style callback as its last argument
Osamu Nakamura 0:a40b9a259b52 1702
Osamu Nakamura 0:a40b9a259b52 1703 Returns a wrapped function with the exact same call signature as the function passed in.
Osamu Nakamura 0:a40b9a259b52 1704
Osamu Nakamura 0:a40b9a259b52 1705 __Example__
Osamu Nakamura 0:a40b9a259b52 1706
Osamu Nakamura 0:a40b9a259b52 1707 ```js
Osamu Nakamura 0:a40b9a259b52 1708 function sometimesAsync(arg, callback) {
Osamu Nakamura 0:a40b9a259b52 1709 if (cache[arg]) {
Osamu Nakamura 0:a40b9a259b52 1710 return callback(null, cache[arg]); // this would be synchronous!!
Osamu Nakamura 0:a40b9a259b52 1711 } else {
Osamu Nakamura 0:a40b9a259b52 1712 doSomeIO(arg, callback); // this IO would be asynchronous
Osamu Nakamura 0:a40b9a259b52 1713 }
Osamu Nakamura 0:a40b9a259b52 1714 }
Osamu Nakamura 0:a40b9a259b52 1715
Osamu Nakamura 0:a40b9a259b52 1716 // this has a risk of stack overflows if many results are cached in a row
Osamu Nakamura 0:a40b9a259b52 1717 async.mapSeries(args, sometimesAsync, done);
Osamu Nakamura 0:a40b9a259b52 1718
Osamu Nakamura 0:a40b9a259b52 1719 // this will defer sometimesAsync's callback if necessary,
Osamu Nakamura 0:a40b9a259b52 1720 // preventing stack overflows
Osamu Nakamura 0:a40b9a259b52 1721 async.mapSeries(args, async.ensureAsync(sometimesAsync), done);
Osamu Nakamura 0:a40b9a259b52 1722
Osamu Nakamura 0:a40b9a259b52 1723 ```
Osamu Nakamura 0:a40b9a259b52 1724
Osamu Nakamura 0:a40b9a259b52 1725 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1726
Osamu Nakamura 0:a40b9a259b52 1727 <a name="constant">
Osamu Nakamura 0:a40b9a259b52 1728 ### constant(values...)
Osamu Nakamura 0:a40b9a259b52 1729
Osamu Nakamura 0:a40b9a259b52 1730 Returns a function that when called, calls-back with the values provided. Useful as the first function in a `waterfall`, or for plugging values in to `auto`.
Osamu Nakamura 0:a40b9a259b52 1731
Osamu Nakamura 0:a40b9a259b52 1732 __Example__
Osamu Nakamura 0:a40b9a259b52 1733
Osamu Nakamura 0:a40b9a259b52 1734 ```js
Osamu Nakamura 0:a40b9a259b52 1735 async.waterfall([
Osamu Nakamura 0:a40b9a259b52 1736 async.constant(42),
Osamu Nakamura 0:a40b9a259b52 1737 function (value, next) {
Osamu Nakamura 0:a40b9a259b52 1738 // value === 42
Osamu Nakamura 0:a40b9a259b52 1739 },
Osamu Nakamura 0:a40b9a259b52 1740 //...
Osamu Nakamura 0:a40b9a259b52 1741 ], callback);
Osamu Nakamura 0:a40b9a259b52 1742
Osamu Nakamura 0:a40b9a259b52 1743 async.waterfall([
Osamu Nakamura 0:a40b9a259b52 1744 async.constant(filename, "utf8"),
Osamu Nakamura 0:a40b9a259b52 1745 fs.readFile,
Osamu Nakamura 0:a40b9a259b52 1746 function (fileData, next) {
Osamu Nakamura 0:a40b9a259b52 1747 //...
Osamu Nakamura 0:a40b9a259b52 1748 }
Osamu Nakamura 0:a40b9a259b52 1749 //...
Osamu Nakamura 0:a40b9a259b52 1750 ], callback);
Osamu Nakamura 0:a40b9a259b52 1751
Osamu Nakamura 0:a40b9a259b52 1752 async.auto({
Osamu Nakamura 0:a40b9a259b52 1753 hostname: async.constant("https://server.net/"),
Osamu Nakamura 0:a40b9a259b52 1754 port: findFreePort,
Osamu Nakamura 0:a40b9a259b52 1755 launchServer: ["hostname", "port", function (cb, options) {
Osamu Nakamura 0:a40b9a259b52 1756 startServer(options, cb);
Osamu Nakamura 0:a40b9a259b52 1757 }],
Osamu Nakamura 0:a40b9a259b52 1758 //...
Osamu Nakamura 0:a40b9a259b52 1759 }, callback);
Osamu Nakamura 0:a40b9a259b52 1760
Osamu Nakamura 0:a40b9a259b52 1761 ```
Osamu Nakamura 0:a40b9a259b52 1762
Osamu Nakamura 0:a40b9a259b52 1763 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1764
Osamu Nakamura 0:a40b9a259b52 1765 <a name="asyncify">
Osamu Nakamura 0:a40b9a259b52 1766 <a name="wrapSync">
Osamu Nakamura 0:a40b9a259b52 1767 ### asyncify(func)
Osamu Nakamura 0:a40b9a259b52 1768
Osamu Nakamura 0:a40b9a259b52 1769 __Alias:__ `wrapSync`
Osamu Nakamura 0:a40b9a259b52 1770
Osamu Nakamura 0:a40b9a259b52 1771 Take a sync function and make it async, passing its return value to a callback. This is useful for plugging sync functions into a waterfall, series, or other async functions. Any arguments passed to the generated function will be passed to the wrapped function (except for the final callback argument). Errors thrown will be passed to the callback.
Osamu Nakamura 0:a40b9a259b52 1772
Osamu Nakamura 0:a40b9a259b52 1773 __Example__
Osamu Nakamura 0:a40b9a259b52 1774
Osamu Nakamura 0:a40b9a259b52 1775 ```js
Osamu Nakamura 0:a40b9a259b52 1776 async.waterfall([
Osamu Nakamura 0:a40b9a259b52 1777 async.apply(fs.readFile, filename, "utf8"),
Osamu Nakamura 0:a40b9a259b52 1778 async.asyncify(JSON.parse),
Osamu Nakamura 0:a40b9a259b52 1779 function (data, next) {
Osamu Nakamura 0:a40b9a259b52 1780 // data is the result of parsing the text.
Osamu Nakamura 0:a40b9a259b52 1781 // If there was a parsing error, it would have been caught.
Osamu Nakamura 0:a40b9a259b52 1782 }
Osamu Nakamura 0:a40b9a259b52 1783 ], callback)
Osamu Nakamura 0:a40b9a259b52 1784 ```
Osamu Nakamura 0:a40b9a259b52 1785
Osamu Nakamura 0:a40b9a259b52 1786 If the function passed to `asyncify` returns a Promise, that promises's resolved/rejected state will be used to call the callback, rather than simply the synchronous return value. Example:
Osamu Nakamura 0:a40b9a259b52 1787
Osamu Nakamura 0:a40b9a259b52 1788 ```js
Osamu Nakamura 0:a40b9a259b52 1789 async.waterfall([
Osamu Nakamura 0:a40b9a259b52 1790 async.apply(fs.readFile, filename, "utf8"),
Osamu Nakamura 0:a40b9a259b52 1791 async.asyncify(function (contents) {
Osamu Nakamura 0:a40b9a259b52 1792 return db.model.create(contents);
Osamu Nakamura 0:a40b9a259b52 1793 }),
Osamu Nakamura 0:a40b9a259b52 1794 function (model, next) {
Osamu Nakamura 0:a40b9a259b52 1795 // `model` is the instantiated model object.
Osamu Nakamura 0:a40b9a259b52 1796 // If there was an error, this function would be skipped.
Osamu Nakamura 0:a40b9a259b52 1797 }
Osamu Nakamura 0:a40b9a259b52 1798 ], callback)
Osamu Nakamura 0:a40b9a259b52 1799 ```
Osamu Nakamura 0:a40b9a259b52 1800
Osamu Nakamura 0:a40b9a259b52 1801 This also means you can asyncify ES2016 `async` functions.
Osamu Nakamura 0:a40b9a259b52 1802
Osamu Nakamura 0:a40b9a259b52 1803 ```js
Osamu Nakamura 0:a40b9a259b52 1804 var q = async.queue(async.asyncify(async function (file) {
Osamu Nakamura 0:a40b9a259b52 1805 var intermediateStep = await processFile(file);
Osamu Nakamura 0:a40b9a259b52 1806 return await somePromise(intermediateStep)
Osamu Nakamura 0:a40b9a259b52 1807 }));
Osamu Nakamura 0:a40b9a259b52 1808
Osamu Nakamura 0:a40b9a259b52 1809 q.push(files);
Osamu Nakamura 0:a40b9a259b52 1810 ```
Osamu Nakamura 0:a40b9a259b52 1811
Osamu Nakamura 0:a40b9a259b52 1812 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1813
Osamu Nakamura 0:a40b9a259b52 1814 <a name="log" />
Osamu Nakamura 0:a40b9a259b52 1815 ### log(function, arguments)
Osamu Nakamura 0:a40b9a259b52 1816
Osamu Nakamura 0:a40b9a259b52 1817 Logs the result of an `async` function to the `console`. Only works in Node.js or
Osamu Nakamura 0:a40b9a259b52 1818 in browsers that support `console.log` and `console.error` (such as FF and Chrome).
Osamu Nakamura 0:a40b9a259b52 1819 If multiple arguments are returned from the async function, `console.log` is
Osamu Nakamura 0:a40b9a259b52 1820 called on each argument in order.
Osamu Nakamura 0:a40b9a259b52 1821
Osamu Nakamura 0:a40b9a259b52 1822 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1823
Osamu Nakamura 0:a40b9a259b52 1824 * `function` - The function you want to eventually apply all arguments to.
Osamu Nakamura 0:a40b9a259b52 1825 * `arguments...` - Any number of arguments to apply to the function.
Osamu Nakamura 0:a40b9a259b52 1826
Osamu Nakamura 0:a40b9a259b52 1827 __Example__
Osamu Nakamura 0:a40b9a259b52 1828
Osamu Nakamura 0:a40b9a259b52 1829 ```js
Osamu Nakamura 0:a40b9a259b52 1830 var hello = function(name, callback){
Osamu Nakamura 0:a40b9a259b52 1831 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 1832 callback(null, 'hello ' + name);
Osamu Nakamura 0:a40b9a259b52 1833 }, 1000);
Osamu Nakamura 0:a40b9a259b52 1834 };
Osamu Nakamura 0:a40b9a259b52 1835 ```
Osamu Nakamura 0:a40b9a259b52 1836 ```js
Osamu Nakamura 0:a40b9a259b52 1837 node> async.log(hello, 'world');
Osamu Nakamura 0:a40b9a259b52 1838 'hello world'
Osamu Nakamura 0:a40b9a259b52 1839 ```
Osamu Nakamura 0:a40b9a259b52 1840
Osamu Nakamura 0:a40b9a259b52 1841 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1842
Osamu Nakamura 0:a40b9a259b52 1843 <a name="dir" />
Osamu Nakamura 0:a40b9a259b52 1844 ### dir(function, arguments)
Osamu Nakamura 0:a40b9a259b52 1845
Osamu Nakamura 0:a40b9a259b52 1846 Logs the result of an `async` function to the `console` using `console.dir` to
Osamu Nakamura 0:a40b9a259b52 1847 display the properties of the resulting object. Only works in Node.js or
Osamu Nakamura 0:a40b9a259b52 1848 in browsers that support `console.dir` and `console.error` (such as FF and Chrome).
Osamu Nakamura 0:a40b9a259b52 1849 If multiple arguments are returned from the async function, `console.dir` is
Osamu Nakamura 0:a40b9a259b52 1850 called on each argument in order.
Osamu Nakamura 0:a40b9a259b52 1851
Osamu Nakamura 0:a40b9a259b52 1852 __Arguments__
Osamu Nakamura 0:a40b9a259b52 1853
Osamu Nakamura 0:a40b9a259b52 1854 * `function` - The function you want to eventually apply all arguments to.
Osamu Nakamura 0:a40b9a259b52 1855 * `arguments...` - Any number of arguments to apply to the function.
Osamu Nakamura 0:a40b9a259b52 1856
Osamu Nakamura 0:a40b9a259b52 1857 __Example__
Osamu Nakamura 0:a40b9a259b52 1858
Osamu Nakamura 0:a40b9a259b52 1859 ```js
Osamu Nakamura 0:a40b9a259b52 1860 var hello = function(name, callback){
Osamu Nakamura 0:a40b9a259b52 1861 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 1862 callback(null, {hello: name});
Osamu Nakamura 0:a40b9a259b52 1863 }, 1000);
Osamu Nakamura 0:a40b9a259b52 1864 };
Osamu Nakamura 0:a40b9a259b52 1865 ```
Osamu Nakamura 0:a40b9a259b52 1866 ```js
Osamu Nakamura 0:a40b9a259b52 1867 node> async.dir(hello, 'world');
Osamu Nakamura 0:a40b9a259b52 1868 {hello: 'world'}
Osamu Nakamura 0:a40b9a259b52 1869 ```
Osamu Nakamura 0:a40b9a259b52 1870
Osamu Nakamura 0:a40b9a259b52 1871 ---------------------------------------
Osamu Nakamura 0:a40b9a259b52 1872
Osamu Nakamura 0:a40b9a259b52 1873 <a name="noConflict" />
Osamu Nakamura 0:a40b9a259b52 1874 ### noConflict()
Osamu Nakamura 0:a40b9a259b52 1875
Osamu Nakamura 0:a40b9a259b52 1876 Changes the value of `async` back to its original value, returning a reference to the
Osamu Nakamura 0:a40b9a259b52 1877 `async` object.