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.
3. When prompted, enter a name for the access key (e.g. "demo") and click ADD.
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:
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:
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:
Then, you should see the following message if the configuration is successfully done, :
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:
- 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:
- How QR Code Login tab works
When you choose QR Code Login tab, you can see the following screen indicating it's Locked status.
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.
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:
- Create your HEROKU account at https://signup.heroku.com/login if you haven't created it yet.
- 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 ) - 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.
- Invoke the command git init
- Invoke the command git add . to prepare all the files staged for the next commit
- Invoke the command git commit -m "[commit message]" to commit the files staged at the step 5
- Invoke the command heroku create. If the command is successfully terminated, the remote repository heroku should be created and associated with the local repository
- 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をクリックします。
3. access keyの名称を入力するように促されたら、任意の名称(例えばdemo等)を入力し、ADDをクリックします。
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フォルダに格納してください。
アプリケーションの実行
本アプリケーションでは、Shopping CartとQR 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/ を参照ください。プログラムが正常に動作している場合、下記のメッセージがターミナルに表示されます。
プログラムの正常動作が確認できたら、以降の手順に従ってWebアプリケーションを実行します。
- Webアプリケーションの起動
下記コマンドでWebアプリケーションを起動可能です。
上述のアプリケーション設定が正常に行われていれば、下記メッセージが表示されます。
なお、8080はPORT設定に応じた値となります。
続いて、上述のURLにWebブラウザでアクセスすると、下記のSmart Shopping Cartの画面が表示されます。
- Shopping Cartタブ
GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode\qrcode.pdf に記載されている Birthday Cake、Party Cups、Beer Kegs、Pound of beef、Buflle-proof vest のQRコードをデコードすると、下記のようにデコードしたアイテムが都度ショッピングカートに追加されます。
- QR Code Loginタブ
このタブを選択すると、下記のLock状態を示す画面が表示されます。
ここで、GR-Peach_mbed-os_QRCode_ShoppingCart_node\qrcode\qrcode.pdf に記載のUnlock QRコードをデコードすると、Unlock状態を示す下記の画面に遷移します。
この後、Lock QRコードをデコードすると画面はLock状態に再度遷移します。
このようにQR Code Loginタブでは、LockとUnlockのQRコードをデコードする都度、対応する画面に遷移するアプリケーションです。
HEROKUへのデプロイ
HEROKU ( https://id.heroku.com) はNode.jsアプリが無償でデプロイ可能なPaaS (Platform as a Service)と呼ばれるサービスです。HEROKUを活用する事で、mbed Shopping CartとQR Code Loginにモバイル端末等からアクセスする事が可能となります。
以下、HEROKUへ本アプリをデプロイする手順を説明します。
- HEROKUのアカウントを所有していない場合は https://signup.heroku.com/login でアカウントを作成してください
- 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 ) - ターミナルソフトウェア(例えばWindows PowerShell)を立上げます。そして本アプリのルートディレクトリへ移動し、heroku loginコマンドを実行します。Emailアドレスとパスワードの入力を求められた場合は、アカウント生成時に入力したアドレスとパスワードを入力してください。
- git initコマンドを実行します
- git add .コマンドを実行し、全ファイルをコミット対象に設定します
- git commit -m "[commit message]" で、全ファイルをコミットします
- heroku createを実行します。本コマンドが正常終了すると、リモートリポジトリ herokuが設定されます
- 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中のhttpsをhttpに置換えたもの)へブラウザ等でアクセスします。途中でエラーが発生していなければ、mbed Shopping CartがWebブラウザ上に表示されます。
node_modules/async/README.md@0:a40b9a259b52, 2018-01-12 (annotated)
- Committer:
- Osamu Nakamura
- Date:
- Fri Jan 12 19:05:14 2018 +0900
- Revision:
- 0:a40b9a259b52
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Osamu Nakamura |
0:a40b9a259b52 | 1 | # Async.js |
Osamu Nakamura |
0:a40b9a259b52 | 2 | |
Osamu Nakamura |
0:a40b9a259b52 | 3 | [](https://travis-ci.org/caolan/async) |
Osamu Nakamura |
0:a40b9a259b52 | 4 | [](https://www.npmjs.org/package/async) |
Osamu Nakamura |
0:a40b9a259b52 | 5 | [](https://coveralls.io/r/caolan/async?branch=master) |
Osamu Nakamura |
0:a40b9a259b52 | 6 | [](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. |