Node.js based smart shopping cart app

Information

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

Getting Started

Installing Node.js and npm

You need to have Node.js and npm installed.

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

node --version
npm --version

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

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

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

Prerequisite

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

Import programGR-PEACH_mbed-os-client-ZXingSample

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

Configuring the Applition

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

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

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

.env

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

.env

PORT=...

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

Application Execution

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

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

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

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

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

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

How to Deploy this app on HEROKU

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

Here is the procedure to deploy this application on HEROKU:

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

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

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

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

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

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

node --version
npm --version

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

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

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

前提条件

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

Import programGR-PEACH_mbed-os-client-ZXingSample

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

アプリケーションの設定

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

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

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

.env

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

.env

PORT=...

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

/media/uploads/HinoNaka/mbed_shoppingcart_fig8.png

アプリケーションの実行

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

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

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

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

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

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

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

HEROKUへのデプロイ

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

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

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

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

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

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Osamu Nakamura 0:a40b9a259b52 1 /*!
Osamu Nakamura 0:a40b9a259b52 2 * async
Osamu Nakamura 0:a40b9a259b52 3 * https://github.com/caolan/async
Osamu Nakamura 0:a40b9a259b52 4 *
Osamu Nakamura 0:a40b9a259b52 5 * Copyright 2010-2014 Caolan McMahon
Osamu Nakamura 0:a40b9a259b52 6 * Released under the MIT license
Osamu Nakamura 0:a40b9a259b52 7 */
Osamu Nakamura 0:a40b9a259b52 8 (function () {
Osamu Nakamura 0:a40b9a259b52 9
Osamu Nakamura 0:a40b9a259b52 10 var async = {};
Osamu Nakamura 0:a40b9a259b52 11 function noop() {}
Osamu Nakamura 0:a40b9a259b52 12 function identity(v) {
Osamu Nakamura 0:a40b9a259b52 13 return v;
Osamu Nakamura 0:a40b9a259b52 14 }
Osamu Nakamura 0:a40b9a259b52 15 function toBool(v) {
Osamu Nakamura 0:a40b9a259b52 16 return !!v;
Osamu Nakamura 0:a40b9a259b52 17 }
Osamu Nakamura 0:a40b9a259b52 18 function notId(v) {
Osamu Nakamura 0:a40b9a259b52 19 return !v;
Osamu Nakamura 0:a40b9a259b52 20 }
Osamu Nakamura 0:a40b9a259b52 21
Osamu Nakamura 0:a40b9a259b52 22 // global on the server, window in the browser
Osamu Nakamura 0:a40b9a259b52 23 var previous_async;
Osamu Nakamura 0:a40b9a259b52 24
Osamu Nakamura 0:a40b9a259b52 25 // Establish the root object, `window` (`self`) in the browser, `global`
Osamu Nakamura 0:a40b9a259b52 26 // on the server, or `this` in some virtual machines. We use `self`
Osamu Nakamura 0:a40b9a259b52 27 // instead of `window` for `WebWorker` support.
Osamu Nakamura 0:a40b9a259b52 28 var root = typeof self === 'object' && self.self === self && self ||
Osamu Nakamura 0:a40b9a259b52 29 typeof global === 'object' && global.global === global && global ||
Osamu Nakamura 0:a40b9a259b52 30 this;
Osamu Nakamura 0:a40b9a259b52 31
Osamu Nakamura 0:a40b9a259b52 32 if (root != null) {
Osamu Nakamura 0:a40b9a259b52 33 previous_async = root.async;
Osamu Nakamura 0:a40b9a259b52 34 }
Osamu Nakamura 0:a40b9a259b52 35
Osamu Nakamura 0:a40b9a259b52 36 async.noConflict = function () {
Osamu Nakamura 0:a40b9a259b52 37 root.async = previous_async;
Osamu Nakamura 0:a40b9a259b52 38 return async;
Osamu Nakamura 0:a40b9a259b52 39 };
Osamu Nakamura 0:a40b9a259b52 40
Osamu Nakamura 0:a40b9a259b52 41 function only_once(fn) {
Osamu Nakamura 0:a40b9a259b52 42 return function() {
Osamu Nakamura 0:a40b9a259b52 43 if (fn === null) throw new Error("Callback was already called.");
Osamu Nakamura 0:a40b9a259b52 44 fn.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 45 fn = null;
Osamu Nakamura 0:a40b9a259b52 46 };
Osamu Nakamura 0:a40b9a259b52 47 }
Osamu Nakamura 0:a40b9a259b52 48
Osamu Nakamura 0:a40b9a259b52 49 function _once(fn) {
Osamu Nakamura 0:a40b9a259b52 50 return function() {
Osamu Nakamura 0:a40b9a259b52 51 if (fn === null) return;
Osamu Nakamura 0:a40b9a259b52 52 fn.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 53 fn = null;
Osamu Nakamura 0:a40b9a259b52 54 };
Osamu Nakamura 0:a40b9a259b52 55 }
Osamu Nakamura 0:a40b9a259b52 56
Osamu Nakamura 0:a40b9a259b52 57 //// cross-browser compatiblity functions ////
Osamu Nakamura 0:a40b9a259b52 58
Osamu Nakamura 0:a40b9a259b52 59 var _toString = Object.prototype.toString;
Osamu Nakamura 0:a40b9a259b52 60
Osamu Nakamura 0:a40b9a259b52 61 var _isArray = Array.isArray || function (obj) {
Osamu Nakamura 0:a40b9a259b52 62 return _toString.call(obj) === '[object Array]';
Osamu Nakamura 0:a40b9a259b52 63 };
Osamu Nakamura 0:a40b9a259b52 64
Osamu Nakamura 0:a40b9a259b52 65 // Ported from underscore.js isObject
Osamu Nakamura 0:a40b9a259b52 66 var _isObject = function(obj) {
Osamu Nakamura 0:a40b9a259b52 67 var type = typeof obj;
Osamu Nakamura 0:a40b9a259b52 68 return type === 'function' || type === 'object' && !!obj;
Osamu Nakamura 0:a40b9a259b52 69 };
Osamu Nakamura 0:a40b9a259b52 70
Osamu Nakamura 0:a40b9a259b52 71 function _isArrayLike(arr) {
Osamu Nakamura 0:a40b9a259b52 72 return _isArray(arr) || (
Osamu Nakamura 0:a40b9a259b52 73 // has a positive integer length property
Osamu Nakamura 0:a40b9a259b52 74 typeof arr.length === "number" &&
Osamu Nakamura 0:a40b9a259b52 75 arr.length >= 0 &&
Osamu Nakamura 0:a40b9a259b52 76 arr.length % 1 === 0
Osamu Nakamura 0:a40b9a259b52 77 );
Osamu Nakamura 0:a40b9a259b52 78 }
Osamu Nakamura 0:a40b9a259b52 79
Osamu Nakamura 0:a40b9a259b52 80 function _arrayEach(arr, iterator) {
Osamu Nakamura 0:a40b9a259b52 81 var index = -1,
Osamu Nakamura 0:a40b9a259b52 82 length = arr.length;
Osamu Nakamura 0:a40b9a259b52 83
Osamu Nakamura 0:a40b9a259b52 84 while (++index < length) {
Osamu Nakamura 0:a40b9a259b52 85 iterator(arr[index], index, arr);
Osamu Nakamura 0:a40b9a259b52 86 }
Osamu Nakamura 0:a40b9a259b52 87 }
Osamu Nakamura 0:a40b9a259b52 88
Osamu Nakamura 0:a40b9a259b52 89 function _map(arr, iterator) {
Osamu Nakamura 0:a40b9a259b52 90 var index = -1,
Osamu Nakamura 0:a40b9a259b52 91 length = arr.length,
Osamu Nakamura 0:a40b9a259b52 92 result = Array(length);
Osamu Nakamura 0:a40b9a259b52 93
Osamu Nakamura 0:a40b9a259b52 94 while (++index < length) {
Osamu Nakamura 0:a40b9a259b52 95 result[index] = iterator(arr[index], index, arr);
Osamu Nakamura 0:a40b9a259b52 96 }
Osamu Nakamura 0:a40b9a259b52 97 return result;
Osamu Nakamura 0:a40b9a259b52 98 }
Osamu Nakamura 0:a40b9a259b52 99
Osamu Nakamura 0:a40b9a259b52 100 function _range(count) {
Osamu Nakamura 0:a40b9a259b52 101 return _map(Array(count), function (v, i) { return i; });
Osamu Nakamura 0:a40b9a259b52 102 }
Osamu Nakamura 0:a40b9a259b52 103
Osamu Nakamura 0:a40b9a259b52 104 function _reduce(arr, iterator, memo) {
Osamu Nakamura 0:a40b9a259b52 105 _arrayEach(arr, function (x, i, a) {
Osamu Nakamura 0:a40b9a259b52 106 memo = iterator(memo, x, i, a);
Osamu Nakamura 0:a40b9a259b52 107 });
Osamu Nakamura 0:a40b9a259b52 108 return memo;
Osamu Nakamura 0:a40b9a259b52 109 }
Osamu Nakamura 0:a40b9a259b52 110
Osamu Nakamura 0:a40b9a259b52 111 function _forEachOf(object, iterator) {
Osamu Nakamura 0:a40b9a259b52 112 _arrayEach(_keys(object), function (key) {
Osamu Nakamura 0:a40b9a259b52 113 iterator(object[key], key);
Osamu Nakamura 0:a40b9a259b52 114 });
Osamu Nakamura 0:a40b9a259b52 115 }
Osamu Nakamura 0:a40b9a259b52 116
Osamu Nakamura 0:a40b9a259b52 117 function _indexOf(arr, item) {
Osamu Nakamura 0:a40b9a259b52 118 for (var i = 0; i < arr.length; i++) {
Osamu Nakamura 0:a40b9a259b52 119 if (arr[i] === item) return i;
Osamu Nakamura 0:a40b9a259b52 120 }
Osamu Nakamura 0:a40b9a259b52 121 return -1;
Osamu Nakamura 0:a40b9a259b52 122 }
Osamu Nakamura 0:a40b9a259b52 123
Osamu Nakamura 0:a40b9a259b52 124 var _keys = Object.keys || function (obj) {
Osamu Nakamura 0:a40b9a259b52 125 var keys = [];
Osamu Nakamura 0:a40b9a259b52 126 for (var k in obj) {
Osamu Nakamura 0:a40b9a259b52 127 if (obj.hasOwnProperty(k)) {
Osamu Nakamura 0:a40b9a259b52 128 keys.push(k);
Osamu Nakamura 0:a40b9a259b52 129 }
Osamu Nakamura 0:a40b9a259b52 130 }
Osamu Nakamura 0:a40b9a259b52 131 return keys;
Osamu Nakamura 0:a40b9a259b52 132 };
Osamu Nakamura 0:a40b9a259b52 133
Osamu Nakamura 0:a40b9a259b52 134 function _keyIterator(coll) {
Osamu Nakamura 0:a40b9a259b52 135 var i = -1;
Osamu Nakamura 0:a40b9a259b52 136 var len;
Osamu Nakamura 0:a40b9a259b52 137 var keys;
Osamu Nakamura 0:a40b9a259b52 138 if (_isArrayLike(coll)) {
Osamu Nakamura 0:a40b9a259b52 139 len = coll.length;
Osamu Nakamura 0:a40b9a259b52 140 return function next() {
Osamu Nakamura 0:a40b9a259b52 141 i++;
Osamu Nakamura 0:a40b9a259b52 142 return i < len ? i : null;
Osamu Nakamura 0:a40b9a259b52 143 };
Osamu Nakamura 0:a40b9a259b52 144 } else {
Osamu Nakamura 0:a40b9a259b52 145 keys = _keys(coll);
Osamu Nakamura 0:a40b9a259b52 146 len = keys.length;
Osamu Nakamura 0:a40b9a259b52 147 return function next() {
Osamu Nakamura 0:a40b9a259b52 148 i++;
Osamu Nakamura 0:a40b9a259b52 149 return i < len ? keys[i] : null;
Osamu Nakamura 0:a40b9a259b52 150 };
Osamu Nakamura 0:a40b9a259b52 151 }
Osamu Nakamura 0:a40b9a259b52 152 }
Osamu Nakamura 0:a40b9a259b52 153
Osamu Nakamura 0:a40b9a259b52 154 // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)
Osamu Nakamura 0:a40b9a259b52 155 // This accumulates the arguments passed into an array, after a given index.
Osamu Nakamura 0:a40b9a259b52 156 // From underscore.js (https://github.com/jashkenas/underscore/pull/2140).
Osamu Nakamura 0:a40b9a259b52 157 function _restParam(func, startIndex) {
Osamu Nakamura 0:a40b9a259b52 158 startIndex = startIndex == null ? func.length - 1 : +startIndex;
Osamu Nakamura 0:a40b9a259b52 159 return function() {
Osamu Nakamura 0:a40b9a259b52 160 var length = Math.max(arguments.length - startIndex, 0);
Osamu Nakamura 0:a40b9a259b52 161 var rest = Array(length);
Osamu Nakamura 0:a40b9a259b52 162 for (var index = 0; index < length; index++) {
Osamu Nakamura 0:a40b9a259b52 163 rest[index] = arguments[index + startIndex];
Osamu Nakamura 0:a40b9a259b52 164 }
Osamu Nakamura 0:a40b9a259b52 165 switch (startIndex) {
Osamu Nakamura 0:a40b9a259b52 166 case 0: return func.call(this, rest);
Osamu Nakamura 0:a40b9a259b52 167 case 1: return func.call(this, arguments[0], rest);
Osamu Nakamura 0:a40b9a259b52 168 }
Osamu Nakamura 0:a40b9a259b52 169 // Currently unused but handle cases outside of the switch statement:
Osamu Nakamura 0:a40b9a259b52 170 // var args = Array(startIndex + 1);
Osamu Nakamura 0:a40b9a259b52 171 // for (index = 0; index < startIndex; index++) {
Osamu Nakamura 0:a40b9a259b52 172 // args[index] = arguments[index];
Osamu Nakamura 0:a40b9a259b52 173 // }
Osamu Nakamura 0:a40b9a259b52 174 // args[startIndex] = rest;
Osamu Nakamura 0:a40b9a259b52 175 // return func.apply(this, args);
Osamu Nakamura 0:a40b9a259b52 176 };
Osamu Nakamura 0:a40b9a259b52 177 }
Osamu Nakamura 0:a40b9a259b52 178
Osamu Nakamura 0:a40b9a259b52 179 function _withoutIndex(iterator) {
Osamu Nakamura 0:a40b9a259b52 180 return function (value, index, callback) {
Osamu Nakamura 0:a40b9a259b52 181 return iterator(value, callback);
Osamu Nakamura 0:a40b9a259b52 182 };
Osamu Nakamura 0:a40b9a259b52 183 }
Osamu Nakamura 0:a40b9a259b52 184
Osamu Nakamura 0:a40b9a259b52 185 //// exported async module functions ////
Osamu Nakamura 0:a40b9a259b52 186
Osamu Nakamura 0:a40b9a259b52 187 //// nextTick implementation with browser-compatible fallback ////
Osamu Nakamura 0:a40b9a259b52 188
Osamu Nakamura 0:a40b9a259b52 189 // capture the global reference to guard against fakeTimer mocks
Osamu Nakamura 0:a40b9a259b52 190 var _setImmediate = typeof setImmediate === 'function' && setImmediate;
Osamu Nakamura 0:a40b9a259b52 191
Osamu Nakamura 0:a40b9a259b52 192 var _delay = _setImmediate ? function(fn) {
Osamu Nakamura 0:a40b9a259b52 193 // not a direct alias for IE10 compatibility
Osamu Nakamura 0:a40b9a259b52 194 _setImmediate(fn);
Osamu Nakamura 0:a40b9a259b52 195 } : function(fn) {
Osamu Nakamura 0:a40b9a259b52 196 setTimeout(fn, 0);
Osamu Nakamura 0:a40b9a259b52 197 };
Osamu Nakamura 0:a40b9a259b52 198
Osamu Nakamura 0:a40b9a259b52 199 if (typeof process === 'object' && typeof process.nextTick === 'function') {
Osamu Nakamura 0:a40b9a259b52 200 async.nextTick = process.nextTick;
Osamu Nakamura 0:a40b9a259b52 201 } else {
Osamu Nakamura 0:a40b9a259b52 202 async.nextTick = _delay;
Osamu Nakamura 0:a40b9a259b52 203 }
Osamu Nakamura 0:a40b9a259b52 204 async.setImmediate = _setImmediate ? _delay : async.nextTick;
Osamu Nakamura 0:a40b9a259b52 205
Osamu Nakamura 0:a40b9a259b52 206
Osamu Nakamura 0:a40b9a259b52 207 async.forEach =
Osamu Nakamura 0:a40b9a259b52 208 async.each = function (arr, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 209 return async.eachOf(arr, _withoutIndex(iterator), callback);
Osamu Nakamura 0:a40b9a259b52 210 };
Osamu Nakamura 0:a40b9a259b52 211
Osamu Nakamura 0:a40b9a259b52 212 async.forEachSeries =
Osamu Nakamura 0:a40b9a259b52 213 async.eachSeries = function (arr, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 214 return async.eachOfSeries(arr, _withoutIndex(iterator), callback);
Osamu Nakamura 0:a40b9a259b52 215 };
Osamu Nakamura 0:a40b9a259b52 216
Osamu Nakamura 0:a40b9a259b52 217
Osamu Nakamura 0:a40b9a259b52 218 async.forEachLimit =
Osamu Nakamura 0:a40b9a259b52 219 async.eachLimit = function (arr, limit, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 220 return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);
Osamu Nakamura 0:a40b9a259b52 221 };
Osamu Nakamura 0:a40b9a259b52 222
Osamu Nakamura 0:a40b9a259b52 223 async.forEachOf =
Osamu Nakamura 0:a40b9a259b52 224 async.eachOf = function (object, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 225 callback = _once(callback || noop);
Osamu Nakamura 0:a40b9a259b52 226 object = object || [];
Osamu Nakamura 0:a40b9a259b52 227
Osamu Nakamura 0:a40b9a259b52 228 var iter = _keyIterator(object);
Osamu Nakamura 0:a40b9a259b52 229 var key, completed = 0;
Osamu Nakamura 0:a40b9a259b52 230
Osamu Nakamura 0:a40b9a259b52 231 while ((key = iter()) != null) {
Osamu Nakamura 0:a40b9a259b52 232 completed += 1;
Osamu Nakamura 0:a40b9a259b52 233 iterator(object[key], key, only_once(done));
Osamu Nakamura 0:a40b9a259b52 234 }
Osamu Nakamura 0:a40b9a259b52 235
Osamu Nakamura 0:a40b9a259b52 236 if (completed === 0) callback(null);
Osamu Nakamura 0:a40b9a259b52 237
Osamu Nakamura 0:a40b9a259b52 238 function done(err) {
Osamu Nakamura 0:a40b9a259b52 239 completed--;
Osamu Nakamura 0:a40b9a259b52 240 if (err) {
Osamu Nakamura 0:a40b9a259b52 241 callback(err);
Osamu Nakamura 0:a40b9a259b52 242 }
Osamu Nakamura 0:a40b9a259b52 243 // Check key is null in case iterator isn't exhausted
Osamu Nakamura 0:a40b9a259b52 244 // and done resolved synchronously.
Osamu Nakamura 0:a40b9a259b52 245 else if (key === null && completed <= 0) {
Osamu Nakamura 0:a40b9a259b52 246 callback(null);
Osamu Nakamura 0:a40b9a259b52 247 }
Osamu Nakamura 0:a40b9a259b52 248 }
Osamu Nakamura 0:a40b9a259b52 249 };
Osamu Nakamura 0:a40b9a259b52 250
Osamu Nakamura 0:a40b9a259b52 251 async.forEachOfSeries =
Osamu Nakamura 0:a40b9a259b52 252 async.eachOfSeries = function (obj, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 253 callback = _once(callback || noop);
Osamu Nakamura 0:a40b9a259b52 254 obj = obj || [];
Osamu Nakamura 0:a40b9a259b52 255 var nextKey = _keyIterator(obj);
Osamu Nakamura 0:a40b9a259b52 256 var key = nextKey();
Osamu Nakamura 0:a40b9a259b52 257 function iterate() {
Osamu Nakamura 0:a40b9a259b52 258 var sync = true;
Osamu Nakamura 0:a40b9a259b52 259 if (key === null) {
Osamu Nakamura 0:a40b9a259b52 260 return callback(null);
Osamu Nakamura 0:a40b9a259b52 261 }
Osamu Nakamura 0:a40b9a259b52 262 iterator(obj[key], key, only_once(function (err) {
Osamu Nakamura 0:a40b9a259b52 263 if (err) {
Osamu Nakamura 0:a40b9a259b52 264 callback(err);
Osamu Nakamura 0:a40b9a259b52 265 }
Osamu Nakamura 0:a40b9a259b52 266 else {
Osamu Nakamura 0:a40b9a259b52 267 key = nextKey();
Osamu Nakamura 0:a40b9a259b52 268 if (key === null) {
Osamu Nakamura 0:a40b9a259b52 269 return callback(null);
Osamu Nakamura 0:a40b9a259b52 270 } else {
Osamu Nakamura 0:a40b9a259b52 271 if (sync) {
Osamu Nakamura 0:a40b9a259b52 272 async.setImmediate(iterate);
Osamu Nakamura 0:a40b9a259b52 273 } else {
Osamu Nakamura 0:a40b9a259b52 274 iterate();
Osamu Nakamura 0:a40b9a259b52 275 }
Osamu Nakamura 0:a40b9a259b52 276 }
Osamu Nakamura 0:a40b9a259b52 277 }
Osamu Nakamura 0:a40b9a259b52 278 }));
Osamu Nakamura 0:a40b9a259b52 279 sync = false;
Osamu Nakamura 0:a40b9a259b52 280 }
Osamu Nakamura 0:a40b9a259b52 281 iterate();
Osamu Nakamura 0:a40b9a259b52 282 };
Osamu Nakamura 0:a40b9a259b52 283
Osamu Nakamura 0:a40b9a259b52 284
Osamu Nakamura 0:a40b9a259b52 285
Osamu Nakamura 0:a40b9a259b52 286 async.forEachOfLimit =
Osamu Nakamura 0:a40b9a259b52 287 async.eachOfLimit = function (obj, limit, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 288 _eachOfLimit(limit)(obj, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 289 };
Osamu Nakamura 0:a40b9a259b52 290
Osamu Nakamura 0:a40b9a259b52 291 function _eachOfLimit(limit) {
Osamu Nakamura 0:a40b9a259b52 292
Osamu Nakamura 0:a40b9a259b52 293 return function (obj, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 294 callback = _once(callback || noop);
Osamu Nakamura 0:a40b9a259b52 295 obj = obj || [];
Osamu Nakamura 0:a40b9a259b52 296 var nextKey = _keyIterator(obj);
Osamu Nakamura 0:a40b9a259b52 297 if (limit <= 0) {
Osamu Nakamura 0:a40b9a259b52 298 return callback(null);
Osamu Nakamura 0:a40b9a259b52 299 }
Osamu Nakamura 0:a40b9a259b52 300 var done = false;
Osamu Nakamura 0:a40b9a259b52 301 var running = 0;
Osamu Nakamura 0:a40b9a259b52 302 var errored = false;
Osamu Nakamura 0:a40b9a259b52 303
Osamu Nakamura 0:a40b9a259b52 304 (function replenish () {
Osamu Nakamura 0:a40b9a259b52 305 if (done && running <= 0) {
Osamu Nakamura 0:a40b9a259b52 306 return callback(null);
Osamu Nakamura 0:a40b9a259b52 307 }
Osamu Nakamura 0:a40b9a259b52 308
Osamu Nakamura 0:a40b9a259b52 309 while (running < limit && !errored) {
Osamu Nakamura 0:a40b9a259b52 310 var key = nextKey();
Osamu Nakamura 0:a40b9a259b52 311 if (key === null) {
Osamu Nakamura 0:a40b9a259b52 312 done = true;
Osamu Nakamura 0:a40b9a259b52 313 if (running <= 0) {
Osamu Nakamura 0:a40b9a259b52 314 callback(null);
Osamu Nakamura 0:a40b9a259b52 315 }
Osamu Nakamura 0:a40b9a259b52 316 return;
Osamu Nakamura 0:a40b9a259b52 317 }
Osamu Nakamura 0:a40b9a259b52 318 running += 1;
Osamu Nakamura 0:a40b9a259b52 319 iterator(obj[key], key, only_once(function (err) {
Osamu Nakamura 0:a40b9a259b52 320 running -= 1;
Osamu Nakamura 0:a40b9a259b52 321 if (err) {
Osamu Nakamura 0:a40b9a259b52 322 callback(err);
Osamu Nakamura 0:a40b9a259b52 323 errored = true;
Osamu Nakamura 0:a40b9a259b52 324 }
Osamu Nakamura 0:a40b9a259b52 325 else {
Osamu Nakamura 0:a40b9a259b52 326 replenish();
Osamu Nakamura 0:a40b9a259b52 327 }
Osamu Nakamura 0:a40b9a259b52 328 }));
Osamu Nakamura 0:a40b9a259b52 329 }
Osamu Nakamura 0:a40b9a259b52 330 })();
Osamu Nakamura 0:a40b9a259b52 331 };
Osamu Nakamura 0:a40b9a259b52 332 }
Osamu Nakamura 0:a40b9a259b52 333
Osamu Nakamura 0:a40b9a259b52 334
Osamu Nakamura 0:a40b9a259b52 335 function doParallel(fn) {
Osamu Nakamura 0:a40b9a259b52 336 return function (obj, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 337 return fn(async.eachOf, obj, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 338 };
Osamu Nakamura 0:a40b9a259b52 339 }
Osamu Nakamura 0:a40b9a259b52 340 function doParallelLimit(fn) {
Osamu Nakamura 0:a40b9a259b52 341 return function (obj, limit, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 342 return fn(_eachOfLimit(limit), obj, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 343 };
Osamu Nakamura 0:a40b9a259b52 344 }
Osamu Nakamura 0:a40b9a259b52 345 function doSeries(fn) {
Osamu Nakamura 0:a40b9a259b52 346 return function (obj, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 347 return fn(async.eachOfSeries, obj, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 348 };
Osamu Nakamura 0:a40b9a259b52 349 }
Osamu Nakamura 0:a40b9a259b52 350
Osamu Nakamura 0:a40b9a259b52 351 function _asyncMap(eachfn, arr, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 352 callback = _once(callback || noop);
Osamu Nakamura 0:a40b9a259b52 353 arr = arr || [];
Osamu Nakamura 0:a40b9a259b52 354 var results = _isArrayLike(arr) ? [] : {};
Osamu Nakamura 0:a40b9a259b52 355 eachfn(arr, function (value, index, callback) {
Osamu Nakamura 0:a40b9a259b52 356 iterator(value, function (err, v) {
Osamu Nakamura 0:a40b9a259b52 357 results[index] = v;
Osamu Nakamura 0:a40b9a259b52 358 callback(err);
Osamu Nakamura 0:a40b9a259b52 359 });
Osamu Nakamura 0:a40b9a259b52 360 }, function (err) {
Osamu Nakamura 0:a40b9a259b52 361 callback(err, results);
Osamu Nakamura 0:a40b9a259b52 362 });
Osamu Nakamura 0:a40b9a259b52 363 }
Osamu Nakamura 0:a40b9a259b52 364
Osamu Nakamura 0:a40b9a259b52 365 async.map = doParallel(_asyncMap);
Osamu Nakamura 0:a40b9a259b52 366 async.mapSeries = doSeries(_asyncMap);
Osamu Nakamura 0:a40b9a259b52 367 async.mapLimit = doParallelLimit(_asyncMap);
Osamu Nakamura 0:a40b9a259b52 368
Osamu Nakamura 0:a40b9a259b52 369 // reduce only has a series version, as doing reduce in parallel won't
Osamu Nakamura 0:a40b9a259b52 370 // work in many situations.
Osamu Nakamura 0:a40b9a259b52 371 async.inject =
Osamu Nakamura 0:a40b9a259b52 372 async.foldl =
Osamu Nakamura 0:a40b9a259b52 373 async.reduce = function (arr, memo, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 374 async.eachOfSeries(arr, function (x, i, callback) {
Osamu Nakamura 0:a40b9a259b52 375 iterator(memo, x, function (err, v) {
Osamu Nakamura 0:a40b9a259b52 376 memo = v;
Osamu Nakamura 0:a40b9a259b52 377 callback(err);
Osamu Nakamura 0:a40b9a259b52 378 });
Osamu Nakamura 0:a40b9a259b52 379 }, function (err) {
Osamu Nakamura 0:a40b9a259b52 380 callback(err, memo);
Osamu Nakamura 0:a40b9a259b52 381 });
Osamu Nakamura 0:a40b9a259b52 382 };
Osamu Nakamura 0:a40b9a259b52 383
Osamu Nakamura 0:a40b9a259b52 384 async.foldr =
Osamu Nakamura 0:a40b9a259b52 385 async.reduceRight = function (arr, memo, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 386 var reversed = _map(arr, identity).reverse();
Osamu Nakamura 0:a40b9a259b52 387 async.reduce(reversed, memo, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 388 };
Osamu Nakamura 0:a40b9a259b52 389
Osamu Nakamura 0:a40b9a259b52 390 async.transform = function (arr, memo, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 391 if (arguments.length === 3) {
Osamu Nakamura 0:a40b9a259b52 392 callback = iterator;
Osamu Nakamura 0:a40b9a259b52 393 iterator = memo;
Osamu Nakamura 0:a40b9a259b52 394 memo = _isArray(arr) ? [] : {};
Osamu Nakamura 0:a40b9a259b52 395 }
Osamu Nakamura 0:a40b9a259b52 396
Osamu Nakamura 0:a40b9a259b52 397 async.eachOf(arr, function(v, k, cb) {
Osamu Nakamura 0:a40b9a259b52 398 iterator(memo, v, k, cb);
Osamu Nakamura 0:a40b9a259b52 399 }, function(err) {
Osamu Nakamura 0:a40b9a259b52 400 callback(err, memo);
Osamu Nakamura 0:a40b9a259b52 401 });
Osamu Nakamura 0:a40b9a259b52 402 };
Osamu Nakamura 0:a40b9a259b52 403
Osamu Nakamura 0:a40b9a259b52 404 function _filter(eachfn, arr, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 405 var results = [];
Osamu Nakamura 0:a40b9a259b52 406 eachfn(arr, function (x, index, callback) {
Osamu Nakamura 0:a40b9a259b52 407 iterator(x, function (v) {
Osamu Nakamura 0:a40b9a259b52 408 if (v) {
Osamu Nakamura 0:a40b9a259b52 409 results.push({index: index, value: x});
Osamu Nakamura 0:a40b9a259b52 410 }
Osamu Nakamura 0:a40b9a259b52 411 callback();
Osamu Nakamura 0:a40b9a259b52 412 });
Osamu Nakamura 0:a40b9a259b52 413 }, function () {
Osamu Nakamura 0:a40b9a259b52 414 callback(_map(results.sort(function (a, b) {
Osamu Nakamura 0:a40b9a259b52 415 return a.index - b.index;
Osamu Nakamura 0:a40b9a259b52 416 }), function (x) {
Osamu Nakamura 0:a40b9a259b52 417 return x.value;
Osamu Nakamura 0:a40b9a259b52 418 }));
Osamu Nakamura 0:a40b9a259b52 419 });
Osamu Nakamura 0:a40b9a259b52 420 }
Osamu Nakamura 0:a40b9a259b52 421
Osamu Nakamura 0:a40b9a259b52 422 async.select =
Osamu Nakamura 0:a40b9a259b52 423 async.filter = doParallel(_filter);
Osamu Nakamura 0:a40b9a259b52 424
Osamu Nakamura 0:a40b9a259b52 425 async.selectLimit =
Osamu Nakamura 0:a40b9a259b52 426 async.filterLimit = doParallelLimit(_filter);
Osamu Nakamura 0:a40b9a259b52 427
Osamu Nakamura 0:a40b9a259b52 428 async.selectSeries =
Osamu Nakamura 0:a40b9a259b52 429 async.filterSeries = doSeries(_filter);
Osamu Nakamura 0:a40b9a259b52 430
Osamu Nakamura 0:a40b9a259b52 431 function _reject(eachfn, arr, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 432 _filter(eachfn, arr, function(value, cb) {
Osamu Nakamura 0:a40b9a259b52 433 iterator(value, function(v) {
Osamu Nakamura 0:a40b9a259b52 434 cb(!v);
Osamu Nakamura 0:a40b9a259b52 435 });
Osamu Nakamura 0:a40b9a259b52 436 }, callback);
Osamu Nakamura 0:a40b9a259b52 437 }
Osamu Nakamura 0:a40b9a259b52 438 async.reject = doParallel(_reject);
Osamu Nakamura 0:a40b9a259b52 439 async.rejectLimit = doParallelLimit(_reject);
Osamu Nakamura 0:a40b9a259b52 440 async.rejectSeries = doSeries(_reject);
Osamu Nakamura 0:a40b9a259b52 441
Osamu Nakamura 0:a40b9a259b52 442 function _createTester(eachfn, check, getResult) {
Osamu Nakamura 0:a40b9a259b52 443 return function(arr, limit, iterator, cb) {
Osamu Nakamura 0:a40b9a259b52 444 function done() {
Osamu Nakamura 0:a40b9a259b52 445 if (cb) cb(getResult(false, void 0));
Osamu Nakamura 0:a40b9a259b52 446 }
Osamu Nakamura 0:a40b9a259b52 447 function iteratee(x, _, callback) {
Osamu Nakamura 0:a40b9a259b52 448 if (!cb) return callback();
Osamu Nakamura 0:a40b9a259b52 449 iterator(x, function (v) {
Osamu Nakamura 0:a40b9a259b52 450 if (cb && check(v)) {
Osamu Nakamura 0:a40b9a259b52 451 cb(getResult(true, x));
Osamu Nakamura 0:a40b9a259b52 452 cb = iterator = false;
Osamu Nakamura 0:a40b9a259b52 453 }
Osamu Nakamura 0:a40b9a259b52 454 callback();
Osamu Nakamura 0:a40b9a259b52 455 });
Osamu Nakamura 0:a40b9a259b52 456 }
Osamu Nakamura 0:a40b9a259b52 457 if (arguments.length > 3) {
Osamu Nakamura 0:a40b9a259b52 458 eachfn(arr, limit, iteratee, done);
Osamu Nakamura 0:a40b9a259b52 459 } else {
Osamu Nakamura 0:a40b9a259b52 460 cb = iterator;
Osamu Nakamura 0:a40b9a259b52 461 iterator = limit;
Osamu Nakamura 0:a40b9a259b52 462 eachfn(arr, iteratee, done);
Osamu Nakamura 0:a40b9a259b52 463 }
Osamu Nakamura 0:a40b9a259b52 464 };
Osamu Nakamura 0:a40b9a259b52 465 }
Osamu Nakamura 0:a40b9a259b52 466
Osamu Nakamura 0:a40b9a259b52 467 async.any =
Osamu Nakamura 0:a40b9a259b52 468 async.some = _createTester(async.eachOf, toBool, identity);
Osamu Nakamura 0:a40b9a259b52 469
Osamu Nakamura 0:a40b9a259b52 470 async.someLimit = _createTester(async.eachOfLimit, toBool, identity);
Osamu Nakamura 0:a40b9a259b52 471
Osamu Nakamura 0:a40b9a259b52 472 async.all =
Osamu Nakamura 0:a40b9a259b52 473 async.every = _createTester(async.eachOf, notId, notId);
Osamu Nakamura 0:a40b9a259b52 474
Osamu Nakamura 0:a40b9a259b52 475 async.everyLimit = _createTester(async.eachOfLimit, notId, notId);
Osamu Nakamura 0:a40b9a259b52 476
Osamu Nakamura 0:a40b9a259b52 477 function _findGetResult(v, x) {
Osamu Nakamura 0:a40b9a259b52 478 return x;
Osamu Nakamura 0:a40b9a259b52 479 }
Osamu Nakamura 0:a40b9a259b52 480 async.detect = _createTester(async.eachOf, identity, _findGetResult);
Osamu Nakamura 0:a40b9a259b52 481 async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);
Osamu Nakamura 0:a40b9a259b52 482 async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);
Osamu Nakamura 0:a40b9a259b52 483
Osamu Nakamura 0:a40b9a259b52 484 async.sortBy = function (arr, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 485 async.map(arr, function (x, callback) {
Osamu Nakamura 0:a40b9a259b52 486 iterator(x, function (err, criteria) {
Osamu Nakamura 0:a40b9a259b52 487 if (err) {
Osamu Nakamura 0:a40b9a259b52 488 callback(err);
Osamu Nakamura 0:a40b9a259b52 489 }
Osamu Nakamura 0:a40b9a259b52 490 else {
Osamu Nakamura 0:a40b9a259b52 491 callback(null, {value: x, criteria: criteria});
Osamu Nakamura 0:a40b9a259b52 492 }
Osamu Nakamura 0:a40b9a259b52 493 });
Osamu Nakamura 0:a40b9a259b52 494 }, function (err, results) {
Osamu Nakamura 0:a40b9a259b52 495 if (err) {
Osamu Nakamura 0:a40b9a259b52 496 return callback(err);
Osamu Nakamura 0:a40b9a259b52 497 }
Osamu Nakamura 0:a40b9a259b52 498 else {
Osamu Nakamura 0:a40b9a259b52 499 callback(null, _map(results.sort(comparator), function (x) {
Osamu Nakamura 0:a40b9a259b52 500 return x.value;
Osamu Nakamura 0:a40b9a259b52 501 }));
Osamu Nakamura 0:a40b9a259b52 502 }
Osamu Nakamura 0:a40b9a259b52 503
Osamu Nakamura 0:a40b9a259b52 504 });
Osamu Nakamura 0:a40b9a259b52 505
Osamu Nakamura 0:a40b9a259b52 506 function comparator(left, right) {
Osamu Nakamura 0:a40b9a259b52 507 var a = left.criteria, b = right.criteria;
Osamu Nakamura 0:a40b9a259b52 508 return a < b ? -1 : a > b ? 1 : 0;
Osamu Nakamura 0:a40b9a259b52 509 }
Osamu Nakamura 0:a40b9a259b52 510 };
Osamu Nakamura 0:a40b9a259b52 511
Osamu Nakamura 0:a40b9a259b52 512 async.auto = function (tasks, concurrency, callback) {
Osamu Nakamura 0:a40b9a259b52 513 if (typeof arguments[1] === 'function') {
Osamu Nakamura 0:a40b9a259b52 514 // concurrency is optional, shift the args.
Osamu Nakamura 0:a40b9a259b52 515 callback = concurrency;
Osamu Nakamura 0:a40b9a259b52 516 concurrency = null;
Osamu Nakamura 0:a40b9a259b52 517 }
Osamu Nakamura 0:a40b9a259b52 518 callback = _once(callback || noop);
Osamu Nakamura 0:a40b9a259b52 519 var keys = _keys(tasks);
Osamu Nakamura 0:a40b9a259b52 520 var remainingTasks = keys.length;
Osamu Nakamura 0:a40b9a259b52 521 if (!remainingTasks) {
Osamu Nakamura 0:a40b9a259b52 522 return callback(null);
Osamu Nakamura 0:a40b9a259b52 523 }
Osamu Nakamura 0:a40b9a259b52 524 if (!concurrency) {
Osamu Nakamura 0:a40b9a259b52 525 concurrency = remainingTasks;
Osamu Nakamura 0:a40b9a259b52 526 }
Osamu Nakamura 0:a40b9a259b52 527
Osamu Nakamura 0:a40b9a259b52 528 var results = {};
Osamu Nakamura 0:a40b9a259b52 529 var runningTasks = 0;
Osamu Nakamura 0:a40b9a259b52 530
Osamu Nakamura 0:a40b9a259b52 531 var hasError = false;
Osamu Nakamura 0:a40b9a259b52 532
Osamu Nakamura 0:a40b9a259b52 533 var listeners = [];
Osamu Nakamura 0:a40b9a259b52 534 function addListener(fn) {
Osamu Nakamura 0:a40b9a259b52 535 listeners.unshift(fn);
Osamu Nakamura 0:a40b9a259b52 536 }
Osamu Nakamura 0:a40b9a259b52 537 function removeListener(fn) {
Osamu Nakamura 0:a40b9a259b52 538 var idx = _indexOf(listeners, fn);
Osamu Nakamura 0:a40b9a259b52 539 if (idx >= 0) listeners.splice(idx, 1);
Osamu Nakamura 0:a40b9a259b52 540 }
Osamu Nakamura 0:a40b9a259b52 541 function taskComplete() {
Osamu Nakamura 0:a40b9a259b52 542 remainingTasks--;
Osamu Nakamura 0:a40b9a259b52 543 _arrayEach(listeners.slice(0), function (fn) {
Osamu Nakamura 0:a40b9a259b52 544 fn();
Osamu Nakamura 0:a40b9a259b52 545 });
Osamu Nakamura 0:a40b9a259b52 546 }
Osamu Nakamura 0:a40b9a259b52 547
Osamu Nakamura 0:a40b9a259b52 548 addListener(function () {
Osamu Nakamura 0:a40b9a259b52 549 if (!remainingTasks) {
Osamu Nakamura 0:a40b9a259b52 550 callback(null, results);
Osamu Nakamura 0:a40b9a259b52 551 }
Osamu Nakamura 0:a40b9a259b52 552 });
Osamu Nakamura 0:a40b9a259b52 553
Osamu Nakamura 0:a40b9a259b52 554 _arrayEach(keys, function (k) {
Osamu Nakamura 0:a40b9a259b52 555 if (hasError) return;
Osamu Nakamura 0:a40b9a259b52 556 var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
Osamu Nakamura 0:a40b9a259b52 557 var taskCallback = _restParam(function(err, args) {
Osamu Nakamura 0:a40b9a259b52 558 runningTasks--;
Osamu Nakamura 0:a40b9a259b52 559 if (args.length <= 1) {
Osamu Nakamura 0:a40b9a259b52 560 args = args[0];
Osamu Nakamura 0:a40b9a259b52 561 }
Osamu Nakamura 0:a40b9a259b52 562 if (err) {
Osamu Nakamura 0:a40b9a259b52 563 var safeResults = {};
Osamu Nakamura 0:a40b9a259b52 564 _forEachOf(results, function(val, rkey) {
Osamu Nakamura 0:a40b9a259b52 565 safeResults[rkey] = val;
Osamu Nakamura 0:a40b9a259b52 566 });
Osamu Nakamura 0:a40b9a259b52 567 safeResults[k] = args;
Osamu Nakamura 0:a40b9a259b52 568 hasError = true;
Osamu Nakamura 0:a40b9a259b52 569
Osamu Nakamura 0:a40b9a259b52 570 callback(err, safeResults);
Osamu Nakamura 0:a40b9a259b52 571 }
Osamu Nakamura 0:a40b9a259b52 572 else {
Osamu Nakamura 0:a40b9a259b52 573 results[k] = args;
Osamu Nakamura 0:a40b9a259b52 574 async.setImmediate(taskComplete);
Osamu Nakamura 0:a40b9a259b52 575 }
Osamu Nakamura 0:a40b9a259b52 576 });
Osamu Nakamura 0:a40b9a259b52 577 var requires = task.slice(0, task.length - 1);
Osamu Nakamura 0:a40b9a259b52 578 // prevent dead-locks
Osamu Nakamura 0:a40b9a259b52 579 var len = requires.length;
Osamu Nakamura 0:a40b9a259b52 580 var dep;
Osamu Nakamura 0:a40b9a259b52 581 while (len--) {
Osamu Nakamura 0:a40b9a259b52 582 if (!(dep = tasks[requires[len]])) {
Osamu Nakamura 0:a40b9a259b52 583 throw new Error('Has nonexistent dependency in ' + requires.join(', '));
Osamu Nakamura 0:a40b9a259b52 584 }
Osamu Nakamura 0:a40b9a259b52 585 if (_isArray(dep) && _indexOf(dep, k) >= 0) {
Osamu Nakamura 0:a40b9a259b52 586 throw new Error('Has cyclic dependencies');
Osamu Nakamura 0:a40b9a259b52 587 }
Osamu Nakamura 0:a40b9a259b52 588 }
Osamu Nakamura 0:a40b9a259b52 589 function ready() {
Osamu Nakamura 0:a40b9a259b52 590 return runningTasks < concurrency && _reduce(requires, function (a, x) {
Osamu Nakamura 0:a40b9a259b52 591 return (a && results.hasOwnProperty(x));
Osamu Nakamura 0:a40b9a259b52 592 }, true) && !results.hasOwnProperty(k);
Osamu Nakamura 0:a40b9a259b52 593 }
Osamu Nakamura 0:a40b9a259b52 594 if (ready()) {
Osamu Nakamura 0:a40b9a259b52 595 runningTasks++;
Osamu Nakamura 0:a40b9a259b52 596 task[task.length - 1](taskCallback, results);
Osamu Nakamura 0:a40b9a259b52 597 }
Osamu Nakamura 0:a40b9a259b52 598 else {
Osamu Nakamura 0:a40b9a259b52 599 addListener(listener);
Osamu Nakamura 0:a40b9a259b52 600 }
Osamu Nakamura 0:a40b9a259b52 601 function listener() {
Osamu Nakamura 0:a40b9a259b52 602 if (ready()) {
Osamu Nakamura 0:a40b9a259b52 603 runningTasks++;
Osamu Nakamura 0:a40b9a259b52 604 removeListener(listener);
Osamu Nakamura 0:a40b9a259b52 605 task[task.length - 1](taskCallback, results);
Osamu Nakamura 0:a40b9a259b52 606 }
Osamu Nakamura 0:a40b9a259b52 607 }
Osamu Nakamura 0:a40b9a259b52 608 });
Osamu Nakamura 0:a40b9a259b52 609 };
Osamu Nakamura 0:a40b9a259b52 610
Osamu Nakamura 0:a40b9a259b52 611
Osamu Nakamura 0:a40b9a259b52 612
Osamu Nakamura 0:a40b9a259b52 613 async.retry = function(times, task, callback) {
Osamu Nakamura 0:a40b9a259b52 614 var DEFAULT_TIMES = 5;
Osamu Nakamura 0:a40b9a259b52 615 var DEFAULT_INTERVAL = 0;
Osamu Nakamura 0:a40b9a259b52 616
Osamu Nakamura 0:a40b9a259b52 617 var attempts = [];
Osamu Nakamura 0:a40b9a259b52 618
Osamu Nakamura 0:a40b9a259b52 619 var opts = {
Osamu Nakamura 0:a40b9a259b52 620 times: DEFAULT_TIMES,
Osamu Nakamura 0:a40b9a259b52 621 interval: DEFAULT_INTERVAL
Osamu Nakamura 0:a40b9a259b52 622 };
Osamu Nakamura 0:a40b9a259b52 623
Osamu Nakamura 0:a40b9a259b52 624 function parseTimes(acc, t){
Osamu Nakamura 0:a40b9a259b52 625 if(typeof t === 'number'){
Osamu Nakamura 0:a40b9a259b52 626 acc.times = parseInt(t, 10) || DEFAULT_TIMES;
Osamu Nakamura 0:a40b9a259b52 627 } else if(typeof t === 'object'){
Osamu Nakamura 0:a40b9a259b52 628 acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;
Osamu Nakamura 0:a40b9a259b52 629 acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;
Osamu Nakamura 0:a40b9a259b52 630 } else {
Osamu Nakamura 0:a40b9a259b52 631 throw new Error('Unsupported argument type for \'times\': ' + typeof t);
Osamu Nakamura 0:a40b9a259b52 632 }
Osamu Nakamura 0:a40b9a259b52 633 }
Osamu Nakamura 0:a40b9a259b52 634
Osamu Nakamura 0:a40b9a259b52 635 var length = arguments.length;
Osamu Nakamura 0:a40b9a259b52 636 if (length < 1 || length > 3) {
Osamu Nakamura 0:a40b9a259b52 637 throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');
Osamu Nakamura 0:a40b9a259b52 638 } else if (length <= 2 && typeof times === 'function') {
Osamu Nakamura 0:a40b9a259b52 639 callback = task;
Osamu Nakamura 0:a40b9a259b52 640 task = times;
Osamu Nakamura 0:a40b9a259b52 641 }
Osamu Nakamura 0:a40b9a259b52 642 if (typeof times !== 'function') {
Osamu Nakamura 0:a40b9a259b52 643 parseTimes(opts, times);
Osamu Nakamura 0:a40b9a259b52 644 }
Osamu Nakamura 0:a40b9a259b52 645 opts.callback = callback;
Osamu Nakamura 0:a40b9a259b52 646 opts.task = task;
Osamu Nakamura 0:a40b9a259b52 647
Osamu Nakamura 0:a40b9a259b52 648 function wrappedTask(wrappedCallback, wrappedResults) {
Osamu Nakamura 0:a40b9a259b52 649 function retryAttempt(task, finalAttempt) {
Osamu Nakamura 0:a40b9a259b52 650 return function(seriesCallback) {
Osamu Nakamura 0:a40b9a259b52 651 task(function(err, result){
Osamu Nakamura 0:a40b9a259b52 652 seriesCallback(!err || finalAttempt, {err: err, result: result});
Osamu Nakamura 0:a40b9a259b52 653 }, wrappedResults);
Osamu Nakamura 0:a40b9a259b52 654 };
Osamu Nakamura 0:a40b9a259b52 655 }
Osamu Nakamura 0:a40b9a259b52 656
Osamu Nakamura 0:a40b9a259b52 657 function retryInterval(interval){
Osamu Nakamura 0:a40b9a259b52 658 return function(seriesCallback){
Osamu Nakamura 0:a40b9a259b52 659 setTimeout(function(){
Osamu Nakamura 0:a40b9a259b52 660 seriesCallback(null);
Osamu Nakamura 0:a40b9a259b52 661 }, interval);
Osamu Nakamura 0:a40b9a259b52 662 };
Osamu Nakamura 0:a40b9a259b52 663 }
Osamu Nakamura 0:a40b9a259b52 664
Osamu Nakamura 0:a40b9a259b52 665 while (opts.times) {
Osamu Nakamura 0:a40b9a259b52 666
Osamu Nakamura 0:a40b9a259b52 667 var finalAttempt = !(opts.times-=1);
Osamu Nakamura 0:a40b9a259b52 668 attempts.push(retryAttempt(opts.task, finalAttempt));
Osamu Nakamura 0:a40b9a259b52 669 if(!finalAttempt && opts.interval > 0){
Osamu Nakamura 0:a40b9a259b52 670 attempts.push(retryInterval(opts.interval));
Osamu Nakamura 0:a40b9a259b52 671 }
Osamu Nakamura 0:a40b9a259b52 672 }
Osamu Nakamura 0:a40b9a259b52 673
Osamu Nakamura 0:a40b9a259b52 674 async.series(attempts, function(done, data){
Osamu Nakamura 0:a40b9a259b52 675 data = data[data.length - 1];
Osamu Nakamura 0:a40b9a259b52 676 (wrappedCallback || opts.callback)(data.err, data.result);
Osamu Nakamura 0:a40b9a259b52 677 });
Osamu Nakamura 0:a40b9a259b52 678 }
Osamu Nakamura 0:a40b9a259b52 679
Osamu Nakamura 0:a40b9a259b52 680 // If a callback is passed, run this as a controll flow
Osamu Nakamura 0:a40b9a259b52 681 return opts.callback ? wrappedTask() : wrappedTask;
Osamu Nakamura 0:a40b9a259b52 682 };
Osamu Nakamura 0:a40b9a259b52 683
Osamu Nakamura 0:a40b9a259b52 684 async.waterfall = function (tasks, callback) {
Osamu Nakamura 0:a40b9a259b52 685 callback = _once(callback || noop);
Osamu Nakamura 0:a40b9a259b52 686 if (!_isArray(tasks)) {
Osamu Nakamura 0:a40b9a259b52 687 var err = new Error('First argument to waterfall must be an array of functions');
Osamu Nakamura 0:a40b9a259b52 688 return callback(err);
Osamu Nakamura 0:a40b9a259b52 689 }
Osamu Nakamura 0:a40b9a259b52 690 if (!tasks.length) {
Osamu Nakamura 0:a40b9a259b52 691 return callback();
Osamu Nakamura 0:a40b9a259b52 692 }
Osamu Nakamura 0:a40b9a259b52 693 function wrapIterator(iterator) {
Osamu Nakamura 0:a40b9a259b52 694 return _restParam(function (err, args) {
Osamu Nakamura 0:a40b9a259b52 695 if (err) {
Osamu Nakamura 0:a40b9a259b52 696 callback.apply(null, [err].concat(args));
Osamu Nakamura 0:a40b9a259b52 697 }
Osamu Nakamura 0:a40b9a259b52 698 else {
Osamu Nakamura 0:a40b9a259b52 699 var next = iterator.next();
Osamu Nakamura 0:a40b9a259b52 700 if (next) {
Osamu Nakamura 0:a40b9a259b52 701 args.push(wrapIterator(next));
Osamu Nakamura 0:a40b9a259b52 702 }
Osamu Nakamura 0:a40b9a259b52 703 else {
Osamu Nakamura 0:a40b9a259b52 704 args.push(callback);
Osamu Nakamura 0:a40b9a259b52 705 }
Osamu Nakamura 0:a40b9a259b52 706 ensureAsync(iterator).apply(null, args);
Osamu Nakamura 0:a40b9a259b52 707 }
Osamu Nakamura 0:a40b9a259b52 708 });
Osamu Nakamura 0:a40b9a259b52 709 }
Osamu Nakamura 0:a40b9a259b52 710 wrapIterator(async.iterator(tasks))();
Osamu Nakamura 0:a40b9a259b52 711 };
Osamu Nakamura 0:a40b9a259b52 712
Osamu Nakamura 0:a40b9a259b52 713 function _parallel(eachfn, tasks, callback) {
Osamu Nakamura 0:a40b9a259b52 714 callback = callback || noop;
Osamu Nakamura 0:a40b9a259b52 715 var results = _isArrayLike(tasks) ? [] : {};
Osamu Nakamura 0:a40b9a259b52 716
Osamu Nakamura 0:a40b9a259b52 717 eachfn(tasks, function (task, key, callback) {
Osamu Nakamura 0:a40b9a259b52 718 task(_restParam(function (err, args) {
Osamu Nakamura 0:a40b9a259b52 719 if (args.length <= 1) {
Osamu Nakamura 0:a40b9a259b52 720 args = args[0];
Osamu Nakamura 0:a40b9a259b52 721 }
Osamu Nakamura 0:a40b9a259b52 722 results[key] = args;
Osamu Nakamura 0:a40b9a259b52 723 callback(err);
Osamu Nakamura 0:a40b9a259b52 724 }));
Osamu Nakamura 0:a40b9a259b52 725 }, function (err) {
Osamu Nakamura 0:a40b9a259b52 726 callback(err, results);
Osamu Nakamura 0:a40b9a259b52 727 });
Osamu Nakamura 0:a40b9a259b52 728 }
Osamu Nakamura 0:a40b9a259b52 729
Osamu Nakamura 0:a40b9a259b52 730 async.parallel = function (tasks, callback) {
Osamu Nakamura 0:a40b9a259b52 731 _parallel(async.eachOf, tasks, callback);
Osamu Nakamura 0:a40b9a259b52 732 };
Osamu Nakamura 0:a40b9a259b52 733
Osamu Nakamura 0:a40b9a259b52 734 async.parallelLimit = function(tasks, limit, callback) {
Osamu Nakamura 0:a40b9a259b52 735 _parallel(_eachOfLimit(limit), tasks, callback);
Osamu Nakamura 0:a40b9a259b52 736 };
Osamu Nakamura 0:a40b9a259b52 737
Osamu Nakamura 0:a40b9a259b52 738 async.series = function(tasks, callback) {
Osamu Nakamura 0:a40b9a259b52 739 _parallel(async.eachOfSeries, tasks, callback);
Osamu Nakamura 0:a40b9a259b52 740 };
Osamu Nakamura 0:a40b9a259b52 741
Osamu Nakamura 0:a40b9a259b52 742 async.iterator = function (tasks) {
Osamu Nakamura 0:a40b9a259b52 743 function makeCallback(index) {
Osamu Nakamura 0:a40b9a259b52 744 function fn() {
Osamu Nakamura 0:a40b9a259b52 745 if (tasks.length) {
Osamu Nakamura 0:a40b9a259b52 746 tasks[index].apply(null, arguments);
Osamu Nakamura 0:a40b9a259b52 747 }
Osamu Nakamura 0:a40b9a259b52 748 return fn.next();
Osamu Nakamura 0:a40b9a259b52 749 }
Osamu Nakamura 0:a40b9a259b52 750 fn.next = function () {
Osamu Nakamura 0:a40b9a259b52 751 return (index < tasks.length - 1) ? makeCallback(index + 1): null;
Osamu Nakamura 0:a40b9a259b52 752 };
Osamu Nakamura 0:a40b9a259b52 753 return fn;
Osamu Nakamura 0:a40b9a259b52 754 }
Osamu Nakamura 0:a40b9a259b52 755 return makeCallback(0);
Osamu Nakamura 0:a40b9a259b52 756 };
Osamu Nakamura 0:a40b9a259b52 757
Osamu Nakamura 0:a40b9a259b52 758 async.apply = _restParam(function (fn, args) {
Osamu Nakamura 0:a40b9a259b52 759 return _restParam(function (callArgs) {
Osamu Nakamura 0:a40b9a259b52 760 return fn.apply(
Osamu Nakamura 0:a40b9a259b52 761 null, args.concat(callArgs)
Osamu Nakamura 0:a40b9a259b52 762 );
Osamu Nakamura 0:a40b9a259b52 763 });
Osamu Nakamura 0:a40b9a259b52 764 });
Osamu Nakamura 0:a40b9a259b52 765
Osamu Nakamura 0:a40b9a259b52 766 function _concat(eachfn, arr, fn, callback) {
Osamu Nakamura 0:a40b9a259b52 767 var result = [];
Osamu Nakamura 0:a40b9a259b52 768 eachfn(arr, function (x, index, cb) {
Osamu Nakamura 0:a40b9a259b52 769 fn(x, function (err, y) {
Osamu Nakamura 0:a40b9a259b52 770 result = result.concat(y || []);
Osamu Nakamura 0:a40b9a259b52 771 cb(err);
Osamu Nakamura 0:a40b9a259b52 772 });
Osamu Nakamura 0:a40b9a259b52 773 }, function (err) {
Osamu Nakamura 0:a40b9a259b52 774 callback(err, result);
Osamu Nakamura 0:a40b9a259b52 775 });
Osamu Nakamura 0:a40b9a259b52 776 }
Osamu Nakamura 0:a40b9a259b52 777 async.concat = doParallel(_concat);
Osamu Nakamura 0:a40b9a259b52 778 async.concatSeries = doSeries(_concat);
Osamu Nakamura 0:a40b9a259b52 779
Osamu Nakamura 0:a40b9a259b52 780 async.whilst = function (test, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 781 callback = callback || noop;
Osamu Nakamura 0:a40b9a259b52 782 if (test()) {
Osamu Nakamura 0:a40b9a259b52 783 var next = _restParam(function(err, args) {
Osamu Nakamura 0:a40b9a259b52 784 if (err) {
Osamu Nakamura 0:a40b9a259b52 785 callback(err);
Osamu Nakamura 0:a40b9a259b52 786 } else if (test.apply(this, args)) {
Osamu Nakamura 0:a40b9a259b52 787 iterator(next);
Osamu Nakamura 0:a40b9a259b52 788 } else {
Osamu Nakamura 0:a40b9a259b52 789 callback.apply(null, [null].concat(args));
Osamu Nakamura 0:a40b9a259b52 790 }
Osamu Nakamura 0:a40b9a259b52 791 });
Osamu Nakamura 0:a40b9a259b52 792 iterator(next);
Osamu Nakamura 0:a40b9a259b52 793 } else {
Osamu Nakamura 0:a40b9a259b52 794 callback(null);
Osamu Nakamura 0:a40b9a259b52 795 }
Osamu Nakamura 0:a40b9a259b52 796 };
Osamu Nakamura 0:a40b9a259b52 797
Osamu Nakamura 0:a40b9a259b52 798 async.doWhilst = function (iterator, test, callback) {
Osamu Nakamura 0:a40b9a259b52 799 var calls = 0;
Osamu Nakamura 0:a40b9a259b52 800 return async.whilst(function() {
Osamu Nakamura 0:a40b9a259b52 801 return ++calls <= 1 || test.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 802 }, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 803 };
Osamu Nakamura 0:a40b9a259b52 804
Osamu Nakamura 0:a40b9a259b52 805 async.until = function (test, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 806 return async.whilst(function() {
Osamu Nakamura 0:a40b9a259b52 807 return !test.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 808 }, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 809 };
Osamu Nakamura 0:a40b9a259b52 810
Osamu Nakamura 0:a40b9a259b52 811 async.doUntil = function (iterator, test, callback) {
Osamu Nakamura 0:a40b9a259b52 812 return async.doWhilst(iterator, function() {
Osamu Nakamura 0:a40b9a259b52 813 return !test.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 814 }, callback);
Osamu Nakamura 0:a40b9a259b52 815 };
Osamu Nakamura 0:a40b9a259b52 816
Osamu Nakamura 0:a40b9a259b52 817 async.during = function (test, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 818 callback = callback || noop;
Osamu Nakamura 0:a40b9a259b52 819
Osamu Nakamura 0:a40b9a259b52 820 var next = _restParam(function(err, args) {
Osamu Nakamura 0:a40b9a259b52 821 if (err) {
Osamu Nakamura 0:a40b9a259b52 822 callback(err);
Osamu Nakamura 0:a40b9a259b52 823 } else {
Osamu Nakamura 0:a40b9a259b52 824 args.push(check);
Osamu Nakamura 0:a40b9a259b52 825 test.apply(this, args);
Osamu Nakamura 0:a40b9a259b52 826 }
Osamu Nakamura 0:a40b9a259b52 827 });
Osamu Nakamura 0:a40b9a259b52 828
Osamu Nakamura 0:a40b9a259b52 829 var check = function(err, truth) {
Osamu Nakamura 0:a40b9a259b52 830 if (err) {
Osamu Nakamura 0:a40b9a259b52 831 callback(err);
Osamu Nakamura 0:a40b9a259b52 832 } else if (truth) {
Osamu Nakamura 0:a40b9a259b52 833 iterator(next);
Osamu Nakamura 0:a40b9a259b52 834 } else {
Osamu Nakamura 0:a40b9a259b52 835 callback(null);
Osamu Nakamura 0:a40b9a259b52 836 }
Osamu Nakamura 0:a40b9a259b52 837 };
Osamu Nakamura 0:a40b9a259b52 838
Osamu Nakamura 0:a40b9a259b52 839 test(check);
Osamu Nakamura 0:a40b9a259b52 840 };
Osamu Nakamura 0:a40b9a259b52 841
Osamu Nakamura 0:a40b9a259b52 842 async.doDuring = function (iterator, test, callback) {
Osamu Nakamura 0:a40b9a259b52 843 var calls = 0;
Osamu Nakamura 0:a40b9a259b52 844 async.during(function(next) {
Osamu Nakamura 0:a40b9a259b52 845 if (calls++ < 1) {
Osamu Nakamura 0:a40b9a259b52 846 next(null, true);
Osamu Nakamura 0:a40b9a259b52 847 } else {
Osamu Nakamura 0:a40b9a259b52 848 test.apply(this, arguments);
Osamu Nakamura 0:a40b9a259b52 849 }
Osamu Nakamura 0:a40b9a259b52 850 }, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 851 };
Osamu Nakamura 0:a40b9a259b52 852
Osamu Nakamura 0:a40b9a259b52 853 function _queue(worker, concurrency, payload) {
Osamu Nakamura 0:a40b9a259b52 854 if (concurrency == null) {
Osamu Nakamura 0:a40b9a259b52 855 concurrency = 1;
Osamu Nakamura 0:a40b9a259b52 856 }
Osamu Nakamura 0:a40b9a259b52 857 else if(concurrency === 0) {
Osamu Nakamura 0:a40b9a259b52 858 throw new Error('Concurrency must not be zero');
Osamu Nakamura 0:a40b9a259b52 859 }
Osamu Nakamura 0:a40b9a259b52 860 function _insert(q, data, pos, callback) {
Osamu Nakamura 0:a40b9a259b52 861 if (callback != null && typeof callback !== "function") {
Osamu Nakamura 0:a40b9a259b52 862 throw new Error("task callback must be a function");
Osamu Nakamura 0:a40b9a259b52 863 }
Osamu Nakamura 0:a40b9a259b52 864 q.started = true;
Osamu Nakamura 0:a40b9a259b52 865 if (!_isArray(data)) {
Osamu Nakamura 0:a40b9a259b52 866 data = [data];
Osamu Nakamura 0:a40b9a259b52 867 }
Osamu Nakamura 0:a40b9a259b52 868 if(data.length === 0 && q.idle()) {
Osamu Nakamura 0:a40b9a259b52 869 // call drain immediately if there are no tasks
Osamu Nakamura 0:a40b9a259b52 870 return async.setImmediate(function() {
Osamu Nakamura 0:a40b9a259b52 871 q.drain();
Osamu Nakamura 0:a40b9a259b52 872 });
Osamu Nakamura 0:a40b9a259b52 873 }
Osamu Nakamura 0:a40b9a259b52 874 _arrayEach(data, function(task) {
Osamu Nakamura 0:a40b9a259b52 875 var item = {
Osamu Nakamura 0:a40b9a259b52 876 data: task,
Osamu Nakamura 0:a40b9a259b52 877 callback: callback || noop
Osamu Nakamura 0:a40b9a259b52 878 };
Osamu Nakamura 0:a40b9a259b52 879
Osamu Nakamura 0:a40b9a259b52 880 if (pos) {
Osamu Nakamura 0:a40b9a259b52 881 q.tasks.unshift(item);
Osamu Nakamura 0:a40b9a259b52 882 } else {
Osamu Nakamura 0:a40b9a259b52 883 q.tasks.push(item);
Osamu Nakamura 0:a40b9a259b52 884 }
Osamu Nakamura 0:a40b9a259b52 885
Osamu Nakamura 0:a40b9a259b52 886 if (q.tasks.length === q.concurrency) {
Osamu Nakamura 0:a40b9a259b52 887 q.saturated();
Osamu Nakamura 0:a40b9a259b52 888 }
Osamu Nakamura 0:a40b9a259b52 889 });
Osamu Nakamura 0:a40b9a259b52 890 async.setImmediate(q.process);
Osamu Nakamura 0:a40b9a259b52 891 }
Osamu Nakamura 0:a40b9a259b52 892 function _next(q, tasks) {
Osamu Nakamura 0:a40b9a259b52 893 return function(){
Osamu Nakamura 0:a40b9a259b52 894 workers -= 1;
Osamu Nakamura 0:a40b9a259b52 895
Osamu Nakamura 0:a40b9a259b52 896 var removed = false;
Osamu Nakamura 0:a40b9a259b52 897 var args = arguments;
Osamu Nakamura 0:a40b9a259b52 898 _arrayEach(tasks, function (task) {
Osamu Nakamura 0:a40b9a259b52 899 _arrayEach(workersList, function (worker, index) {
Osamu Nakamura 0:a40b9a259b52 900 if (worker === task && !removed) {
Osamu Nakamura 0:a40b9a259b52 901 workersList.splice(index, 1);
Osamu Nakamura 0:a40b9a259b52 902 removed = true;
Osamu Nakamura 0:a40b9a259b52 903 }
Osamu Nakamura 0:a40b9a259b52 904 });
Osamu Nakamura 0:a40b9a259b52 905
Osamu Nakamura 0:a40b9a259b52 906 task.callback.apply(task, args);
Osamu Nakamura 0:a40b9a259b52 907 });
Osamu Nakamura 0:a40b9a259b52 908 if (q.tasks.length + workers === 0) {
Osamu Nakamura 0:a40b9a259b52 909 q.drain();
Osamu Nakamura 0:a40b9a259b52 910 }
Osamu Nakamura 0:a40b9a259b52 911 q.process();
Osamu Nakamura 0:a40b9a259b52 912 };
Osamu Nakamura 0:a40b9a259b52 913 }
Osamu Nakamura 0:a40b9a259b52 914
Osamu Nakamura 0:a40b9a259b52 915 var workers = 0;
Osamu Nakamura 0:a40b9a259b52 916 var workersList = [];
Osamu Nakamura 0:a40b9a259b52 917 var q = {
Osamu Nakamura 0:a40b9a259b52 918 tasks: [],
Osamu Nakamura 0:a40b9a259b52 919 concurrency: concurrency,
Osamu Nakamura 0:a40b9a259b52 920 payload: payload,
Osamu Nakamura 0:a40b9a259b52 921 saturated: noop,
Osamu Nakamura 0:a40b9a259b52 922 empty: noop,
Osamu Nakamura 0:a40b9a259b52 923 drain: noop,
Osamu Nakamura 0:a40b9a259b52 924 started: false,
Osamu Nakamura 0:a40b9a259b52 925 paused: false,
Osamu Nakamura 0:a40b9a259b52 926 push: function (data, callback) {
Osamu Nakamura 0:a40b9a259b52 927 _insert(q, data, false, callback);
Osamu Nakamura 0:a40b9a259b52 928 },
Osamu Nakamura 0:a40b9a259b52 929 kill: function () {
Osamu Nakamura 0:a40b9a259b52 930 q.drain = noop;
Osamu Nakamura 0:a40b9a259b52 931 q.tasks = [];
Osamu Nakamura 0:a40b9a259b52 932 },
Osamu Nakamura 0:a40b9a259b52 933 unshift: function (data, callback) {
Osamu Nakamura 0:a40b9a259b52 934 _insert(q, data, true, callback);
Osamu Nakamura 0:a40b9a259b52 935 },
Osamu Nakamura 0:a40b9a259b52 936 process: function () {
Osamu Nakamura 0:a40b9a259b52 937 while(!q.paused && workers < q.concurrency && q.tasks.length){
Osamu Nakamura 0:a40b9a259b52 938
Osamu Nakamura 0:a40b9a259b52 939 var tasks = q.payload ?
Osamu Nakamura 0:a40b9a259b52 940 q.tasks.splice(0, q.payload) :
Osamu Nakamura 0:a40b9a259b52 941 q.tasks.splice(0, q.tasks.length);
Osamu Nakamura 0:a40b9a259b52 942
Osamu Nakamura 0:a40b9a259b52 943 var data = _map(tasks, function (task) {
Osamu Nakamura 0:a40b9a259b52 944 return task.data;
Osamu Nakamura 0:a40b9a259b52 945 });
Osamu Nakamura 0:a40b9a259b52 946
Osamu Nakamura 0:a40b9a259b52 947 if (q.tasks.length === 0) {
Osamu Nakamura 0:a40b9a259b52 948 q.empty();
Osamu Nakamura 0:a40b9a259b52 949 }
Osamu Nakamura 0:a40b9a259b52 950 workers += 1;
Osamu Nakamura 0:a40b9a259b52 951 workersList.push(tasks[0]);
Osamu Nakamura 0:a40b9a259b52 952 var cb = only_once(_next(q, tasks));
Osamu Nakamura 0:a40b9a259b52 953 worker(data, cb);
Osamu Nakamura 0:a40b9a259b52 954 }
Osamu Nakamura 0:a40b9a259b52 955 },
Osamu Nakamura 0:a40b9a259b52 956 length: function () {
Osamu Nakamura 0:a40b9a259b52 957 return q.tasks.length;
Osamu Nakamura 0:a40b9a259b52 958 },
Osamu Nakamura 0:a40b9a259b52 959 running: function () {
Osamu Nakamura 0:a40b9a259b52 960 return workers;
Osamu Nakamura 0:a40b9a259b52 961 },
Osamu Nakamura 0:a40b9a259b52 962 workersList: function () {
Osamu Nakamura 0:a40b9a259b52 963 return workersList;
Osamu Nakamura 0:a40b9a259b52 964 },
Osamu Nakamura 0:a40b9a259b52 965 idle: function() {
Osamu Nakamura 0:a40b9a259b52 966 return q.tasks.length + workers === 0;
Osamu Nakamura 0:a40b9a259b52 967 },
Osamu Nakamura 0:a40b9a259b52 968 pause: function () {
Osamu Nakamura 0:a40b9a259b52 969 q.paused = true;
Osamu Nakamura 0:a40b9a259b52 970 },
Osamu Nakamura 0:a40b9a259b52 971 resume: function () {
Osamu Nakamura 0:a40b9a259b52 972 if (q.paused === false) { return; }
Osamu Nakamura 0:a40b9a259b52 973 q.paused = false;
Osamu Nakamura 0:a40b9a259b52 974 var resumeCount = Math.min(q.concurrency, q.tasks.length);
Osamu Nakamura 0:a40b9a259b52 975 // Need to call q.process once per concurrent
Osamu Nakamura 0:a40b9a259b52 976 // worker to preserve full concurrency after pause
Osamu Nakamura 0:a40b9a259b52 977 for (var w = 1; w <= resumeCount; w++) {
Osamu Nakamura 0:a40b9a259b52 978 async.setImmediate(q.process);
Osamu Nakamura 0:a40b9a259b52 979 }
Osamu Nakamura 0:a40b9a259b52 980 }
Osamu Nakamura 0:a40b9a259b52 981 };
Osamu Nakamura 0:a40b9a259b52 982 return q;
Osamu Nakamura 0:a40b9a259b52 983 }
Osamu Nakamura 0:a40b9a259b52 984
Osamu Nakamura 0:a40b9a259b52 985 async.queue = function (worker, concurrency) {
Osamu Nakamura 0:a40b9a259b52 986 var q = _queue(function (items, cb) {
Osamu Nakamura 0:a40b9a259b52 987 worker(items[0], cb);
Osamu Nakamura 0:a40b9a259b52 988 }, concurrency, 1);
Osamu Nakamura 0:a40b9a259b52 989
Osamu Nakamura 0:a40b9a259b52 990 return q;
Osamu Nakamura 0:a40b9a259b52 991 };
Osamu Nakamura 0:a40b9a259b52 992
Osamu Nakamura 0:a40b9a259b52 993 async.priorityQueue = function (worker, concurrency) {
Osamu Nakamura 0:a40b9a259b52 994
Osamu Nakamura 0:a40b9a259b52 995 function _compareTasks(a, b){
Osamu Nakamura 0:a40b9a259b52 996 return a.priority - b.priority;
Osamu Nakamura 0:a40b9a259b52 997 }
Osamu Nakamura 0:a40b9a259b52 998
Osamu Nakamura 0:a40b9a259b52 999 function _binarySearch(sequence, item, compare) {
Osamu Nakamura 0:a40b9a259b52 1000 var beg = -1,
Osamu Nakamura 0:a40b9a259b52 1001 end = sequence.length - 1;
Osamu Nakamura 0:a40b9a259b52 1002 while (beg < end) {
Osamu Nakamura 0:a40b9a259b52 1003 var mid = beg + ((end - beg + 1) >>> 1);
Osamu Nakamura 0:a40b9a259b52 1004 if (compare(item, sequence[mid]) >= 0) {
Osamu Nakamura 0:a40b9a259b52 1005 beg = mid;
Osamu Nakamura 0:a40b9a259b52 1006 } else {
Osamu Nakamura 0:a40b9a259b52 1007 end = mid - 1;
Osamu Nakamura 0:a40b9a259b52 1008 }
Osamu Nakamura 0:a40b9a259b52 1009 }
Osamu Nakamura 0:a40b9a259b52 1010 return beg;
Osamu Nakamura 0:a40b9a259b52 1011 }
Osamu Nakamura 0:a40b9a259b52 1012
Osamu Nakamura 0:a40b9a259b52 1013 function _insert(q, data, priority, callback) {
Osamu Nakamura 0:a40b9a259b52 1014 if (callback != null && typeof callback !== "function") {
Osamu Nakamura 0:a40b9a259b52 1015 throw new Error("task callback must be a function");
Osamu Nakamura 0:a40b9a259b52 1016 }
Osamu Nakamura 0:a40b9a259b52 1017 q.started = true;
Osamu Nakamura 0:a40b9a259b52 1018 if (!_isArray(data)) {
Osamu Nakamura 0:a40b9a259b52 1019 data = [data];
Osamu Nakamura 0:a40b9a259b52 1020 }
Osamu Nakamura 0:a40b9a259b52 1021 if(data.length === 0) {
Osamu Nakamura 0:a40b9a259b52 1022 // call drain immediately if there are no tasks
Osamu Nakamura 0:a40b9a259b52 1023 return async.setImmediate(function() {
Osamu Nakamura 0:a40b9a259b52 1024 q.drain();
Osamu Nakamura 0:a40b9a259b52 1025 });
Osamu Nakamura 0:a40b9a259b52 1026 }
Osamu Nakamura 0:a40b9a259b52 1027 _arrayEach(data, function(task) {
Osamu Nakamura 0:a40b9a259b52 1028 var item = {
Osamu Nakamura 0:a40b9a259b52 1029 data: task,
Osamu Nakamura 0:a40b9a259b52 1030 priority: priority,
Osamu Nakamura 0:a40b9a259b52 1031 callback: typeof callback === 'function' ? callback : noop
Osamu Nakamura 0:a40b9a259b52 1032 };
Osamu Nakamura 0:a40b9a259b52 1033
Osamu Nakamura 0:a40b9a259b52 1034 q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
Osamu Nakamura 0:a40b9a259b52 1035
Osamu Nakamura 0:a40b9a259b52 1036 if (q.tasks.length === q.concurrency) {
Osamu Nakamura 0:a40b9a259b52 1037 q.saturated();
Osamu Nakamura 0:a40b9a259b52 1038 }
Osamu Nakamura 0:a40b9a259b52 1039 async.setImmediate(q.process);
Osamu Nakamura 0:a40b9a259b52 1040 });
Osamu Nakamura 0:a40b9a259b52 1041 }
Osamu Nakamura 0:a40b9a259b52 1042
Osamu Nakamura 0:a40b9a259b52 1043 // Start with a normal queue
Osamu Nakamura 0:a40b9a259b52 1044 var q = async.queue(worker, concurrency);
Osamu Nakamura 0:a40b9a259b52 1045
Osamu Nakamura 0:a40b9a259b52 1046 // Override push to accept second parameter representing priority
Osamu Nakamura 0:a40b9a259b52 1047 q.push = function (data, priority, callback) {
Osamu Nakamura 0:a40b9a259b52 1048 _insert(q, data, priority, callback);
Osamu Nakamura 0:a40b9a259b52 1049 };
Osamu Nakamura 0:a40b9a259b52 1050
Osamu Nakamura 0:a40b9a259b52 1051 // Remove unshift function
Osamu Nakamura 0:a40b9a259b52 1052 delete q.unshift;
Osamu Nakamura 0:a40b9a259b52 1053
Osamu Nakamura 0:a40b9a259b52 1054 return q;
Osamu Nakamura 0:a40b9a259b52 1055 };
Osamu Nakamura 0:a40b9a259b52 1056
Osamu Nakamura 0:a40b9a259b52 1057 async.cargo = function (worker, payload) {
Osamu Nakamura 0:a40b9a259b52 1058 return _queue(worker, 1, payload);
Osamu Nakamura 0:a40b9a259b52 1059 };
Osamu Nakamura 0:a40b9a259b52 1060
Osamu Nakamura 0:a40b9a259b52 1061 function _console_fn(name) {
Osamu Nakamura 0:a40b9a259b52 1062 return _restParam(function (fn, args) {
Osamu Nakamura 0:a40b9a259b52 1063 fn.apply(null, args.concat([_restParam(function (err, args) {
Osamu Nakamura 0:a40b9a259b52 1064 if (typeof console === 'object') {
Osamu Nakamura 0:a40b9a259b52 1065 if (err) {
Osamu Nakamura 0:a40b9a259b52 1066 if (console.error) {
Osamu Nakamura 0:a40b9a259b52 1067 console.error(err);
Osamu Nakamura 0:a40b9a259b52 1068 }
Osamu Nakamura 0:a40b9a259b52 1069 }
Osamu Nakamura 0:a40b9a259b52 1070 else if (console[name]) {
Osamu Nakamura 0:a40b9a259b52 1071 _arrayEach(args, function (x) {
Osamu Nakamura 0:a40b9a259b52 1072 console[name](x);
Osamu Nakamura 0:a40b9a259b52 1073 });
Osamu Nakamura 0:a40b9a259b52 1074 }
Osamu Nakamura 0:a40b9a259b52 1075 }
Osamu Nakamura 0:a40b9a259b52 1076 })]));
Osamu Nakamura 0:a40b9a259b52 1077 });
Osamu Nakamura 0:a40b9a259b52 1078 }
Osamu Nakamura 0:a40b9a259b52 1079 async.log = _console_fn('log');
Osamu Nakamura 0:a40b9a259b52 1080 async.dir = _console_fn('dir');
Osamu Nakamura 0:a40b9a259b52 1081 /*async.info = _console_fn('info');
Osamu Nakamura 0:a40b9a259b52 1082 async.warn = _console_fn('warn');
Osamu Nakamura 0:a40b9a259b52 1083 async.error = _console_fn('error');*/
Osamu Nakamura 0:a40b9a259b52 1084
Osamu Nakamura 0:a40b9a259b52 1085 async.memoize = function (fn, hasher) {
Osamu Nakamura 0:a40b9a259b52 1086 var memo = {};
Osamu Nakamura 0:a40b9a259b52 1087 var queues = {};
Osamu Nakamura 0:a40b9a259b52 1088 var has = Object.prototype.hasOwnProperty;
Osamu Nakamura 0:a40b9a259b52 1089 hasher = hasher || identity;
Osamu Nakamura 0:a40b9a259b52 1090 var memoized = _restParam(function memoized(args) {
Osamu Nakamura 0:a40b9a259b52 1091 var callback = args.pop();
Osamu Nakamura 0:a40b9a259b52 1092 var key = hasher.apply(null, args);
Osamu Nakamura 0:a40b9a259b52 1093 if (has.call(memo, key)) {
Osamu Nakamura 0:a40b9a259b52 1094 async.setImmediate(function () {
Osamu Nakamura 0:a40b9a259b52 1095 callback.apply(null, memo[key]);
Osamu Nakamura 0:a40b9a259b52 1096 });
Osamu Nakamura 0:a40b9a259b52 1097 }
Osamu Nakamura 0:a40b9a259b52 1098 else if (has.call(queues, key)) {
Osamu Nakamura 0:a40b9a259b52 1099 queues[key].push(callback);
Osamu Nakamura 0:a40b9a259b52 1100 }
Osamu Nakamura 0:a40b9a259b52 1101 else {
Osamu Nakamura 0:a40b9a259b52 1102 queues[key] = [callback];
Osamu Nakamura 0:a40b9a259b52 1103 fn.apply(null, args.concat([_restParam(function (args) {
Osamu Nakamura 0:a40b9a259b52 1104 memo[key] = args;
Osamu Nakamura 0:a40b9a259b52 1105 var q = queues[key];
Osamu Nakamura 0:a40b9a259b52 1106 delete queues[key];
Osamu Nakamura 0:a40b9a259b52 1107 for (var i = 0, l = q.length; i < l; i++) {
Osamu Nakamura 0:a40b9a259b52 1108 q[i].apply(null, args);
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 memoized.memo = memo;
Osamu Nakamura 0:a40b9a259b52 1114 memoized.unmemoized = fn;
Osamu Nakamura 0:a40b9a259b52 1115 return memoized;
Osamu Nakamura 0:a40b9a259b52 1116 };
Osamu Nakamura 0:a40b9a259b52 1117
Osamu Nakamura 0:a40b9a259b52 1118 async.unmemoize = function (fn) {
Osamu Nakamura 0:a40b9a259b52 1119 return function () {
Osamu Nakamura 0:a40b9a259b52 1120 return (fn.unmemoized || fn).apply(null, arguments);
Osamu Nakamura 0:a40b9a259b52 1121 };
Osamu Nakamura 0:a40b9a259b52 1122 };
Osamu Nakamura 0:a40b9a259b52 1123
Osamu Nakamura 0:a40b9a259b52 1124 function _times(mapper) {
Osamu Nakamura 0:a40b9a259b52 1125 return function (count, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 1126 mapper(_range(count), iterator, callback);
Osamu Nakamura 0:a40b9a259b52 1127 };
Osamu Nakamura 0:a40b9a259b52 1128 }
Osamu Nakamura 0:a40b9a259b52 1129
Osamu Nakamura 0:a40b9a259b52 1130 async.times = _times(async.map);
Osamu Nakamura 0:a40b9a259b52 1131 async.timesSeries = _times(async.mapSeries);
Osamu Nakamura 0:a40b9a259b52 1132 async.timesLimit = function (count, limit, iterator, callback) {
Osamu Nakamura 0:a40b9a259b52 1133 return async.mapLimit(_range(count), limit, iterator, callback);
Osamu Nakamura 0:a40b9a259b52 1134 };
Osamu Nakamura 0:a40b9a259b52 1135
Osamu Nakamura 0:a40b9a259b52 1136 async.seq = function (/* functions... */) {
Osamu Nakamura 0:a40b9a259b52 1137 var fns = arguments;
Osamu Nakamura 0:a40b9a259b52 1138 return _restParam(function (args) {
Osamu Nakamura 0:a40b9a259b52 1139 var that = this;
Osamu Nakamura 0:a40b9a259b52 1140
Osamu Nakamura 0:a40b9a259b52 1141 var callback = args[args.length - 1];
Osamu Nakamura 0:a40b9a259b52 1142 if (typeof callback == 'function') {
Osamu Nakamura 0:a40b9a259b52 1143 args.pop();
Osamu Nakamura 0:a40b9a259b52 1144 } else {
Osamu Nakamura 0:a40b9a259b52 1145 callback = noop;
Osamu Nakamura 0:a40b9a259b52 1146 }
Osamu Nakamura 0:a40b9a259b52 1147
Osamu Nakamura 0:a40b9a259b52 1148 async.reduce(fns, args, function (newargs, fn, cb) {
Osamu Nakamura 0:a40b9a259b52 1149 fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {
Osamu Nakamura 0:a40b9a259b52 1150 cb(err, nextargs);
Osamu Nakamura 0:a40b9a259b52 1151 })]));
Osamu Nakamura 0:a40b9a259b52 1152 },
Osamu Nakamura 0:a40b9a259b52 1153 function (err, results) {
Osamu Nakamura 0:a40b9a259b52 1154 callback.apply(that, [err].concat(results));
Osamu Nakamura 0:a40b9a259b52 1155 });
Osamu Nakamura 0:a40b9a259b52 1156 });
Osamu Nakamura 0:a40b9a259b52 1157 };
Osamu Nakamura 0:a40b9a259b52 1158
Osamu Nakamura 0:a40b9a259b52 1159 async.compose = function (/* functions... */) {
Osamu Nakamura 0:a40b9a259b52 1160 return async.seq.apply(null, Array.prototype.reverse.call(arguments));
Osamu Nakamura 0:a40b9a259b52 1161 };
Osamu Nakamura 0:a40b9a259b52 1162
Osamu Nakamura 0:a40b9a259b52 1163
Osamu Nakamura 0:a40b9a259b52 1164 function _applyEach(eachfn) {
Osamu Nakamura 0:a40b9a259b52 1165 return _restParam(function(fns, args) {
Osamu Nakamura 0:a40b9a259b52 1166 var go = _restParam(function(args) {
Osamu Nakamura 0:a40b9a259b52 1167 var that = this;
Osamu Nakamura 0:a40b9a259b52 1168 var callback = args.pop();
Osamu Nakamura 0:a40b9a259b52 1169 return eachfn(fns, function (fn, _, cb) {
Osamu Nakamura 0:a40b9a259b52 1170 fn.apply(that, args.concat([cb]));
Osamu Nakamura 0:a40b9a259b52 1171 },
Osamu Nakamura 0:a40b9a259b52 1172 callback);
Osamu Nakamura 0:a40b9a259b52 1173 });
Osamu Nakamura 0:a40b9a259b52 1174 if (args.length) {
Osamu Nakamura 0:a40b9a259b52 1175 return go.apply(this, args);
Osamu Nakamura 0:a40b9a259b52 1176 }
Osamu Nakamura 0:a40b9a259b52 1177 else {
Osamu Nakamura 0:a40b9a259b52 1178 return go;
Osamu Nakamura 0:a40b9a259b52 1179 }
Osamu Nakamura 0:a40b9a259b52 1180 });
Osamu Nakamura 0:a40b9a259b52 1181 }
Osamu Nakamura 0:a40b9a259b52 1182
Osamu Nakamura 0:a40b9a259b52 1183 async.applyEach = _applyEach(async.eachOf);
Osamu Nakamura 0:a40b9a259b52 1184 async.applyEachSeries = _applyEach(async.eachOfSeries);
Osamu Nakamura 0:a40b9a259b52 1185
Osamu Nakamura 0:a40b9a259b52 1186
Osamu Nakamura 0:a40b9a259b52 1187 async.forever = function (fn, callback) {
Osamu Nakamura 0:a40b9a259b52 1188 var done = only_once(callback || noop);
Osamu Nakamura 0:a40b9a259b52 1189 var task = ensureAsync(fn);
Osamu Nakamura 0:a40b9a259b52 1190 function next(err) {
Osamu Nakamura 0:a40b9a259b52 1191 if (err) {
Osamu Nakamura 0:a40b9a259b52 1192 return done(err);
Osamu Nakamura 0:a40b9a259b52 1193 }
Osamu Nakamura 0:a40b9a259b52 1194 task(next);
Osamu Nakamura 0:a40b9a259b52 1195 }
Osamu Nakamura 0:a40b9a259b52 1196 next();
Osamu Nakamura 0:a40b9a259b52 1197 };
Osamu Nakamura 0:a40b9a259b52 1198
Osamu Nakamura 0:a40b9a259b52 1199 function ensureAsync(fn) {
Osamu Nakamura 0:a40b9a259b52 1200 return _restParam(function (args) {
Osamu Nakamura 0:a40b9a259b52 1201 var callback = args.pop();
Osamu Nakamura 0:a40b9a259b52 1202 args.push(function () {
Osamu Nakamura 0:a40b9a259b52 1203 var innerArgs = arguments;
Osamu Nakamura 0:a40b9a259b52 1204 if (sync) {
Osamu Nakamura 0:a40b9a259b52 1205 async.setImmediate(function () {
Osamu Nakamura 0:a40b9a259b52 1206 callback.apply(null, innerArgs);
Osamu Nakamura 0:a40b9a259b52 1207 });
Osamu Nakamura 0:a40b9a259b52 1208 } else {
Osamu Nakamura 0:a40b9a259b52 1209 callback.apply(null, innerArgs);
Osamu Nakamura 0:a40b9a259b52 1210 }
Osamu Nakamura 0:a40b9a259b52 1211 });
Osamu Nakamura 0:a40b9a259b52 1212 var sync = true;
Osamu Nakamura 0:a40b9a259b52 1213 fn.apply(this, args);
Osamu Nakamura 0:a40b9a259b52 1214 sync = false;
Osamu Nakamura 0:a40b9a259b52 1215 });
Osamu Nakamura 0:a40b9a259b52 1216 }
Osamu Nakamura 0:a40b9a259b52 1217
Osamu Nakamura 0:a40b9a259b52 1218 async.ensureAsync = ensureAsync;
Osamu Nakamura 0:a40b9a259b52 1219
Osamu Nakamura 0:a40b9a259b52 1220 async.constant = _restParam(function(values) {
Osamu Nakamura 0:a40b9a259b52 1221 var args = [null].concat(values);
Osamu Nakamura 0:a40b9a259b52 1222 return function (callback) {
Osamu Nakamura 0:a40b9a259b52 1223 return callback.apply(this, args);
Osamu Nakamura 0:a40b9a259b52 1224 };
Osamu Nakamura 0:a40b9a259b52 1225 });
Osamu Nakamura 0:a40b9a259b52 1226
Osamu Nakamura 0:a40b9a259b52 1227 async.wrapSync =
Osamu Nakamura 0:a40b9a259b52 1228 async.asyncify = function asyncify(func) {
Osamu Nakamura 0:a40b9a259b52 1229 return _restParam(function (args) {
Osamu Nakamura 0:a40b9a259b52 1230 var callback = args.pop();
Osamu Nakamura 0:a40b9a259b52 1231 var result;
Osamu Nakamura 0:a40b9a259b52 1232 try {
Osamu Nakamura 0:a40b9a259b52 1233 result = func.apply(this, args);
Osamu Nakamura 0:a40b9a259b52 1234 } catch (e) {
Osamu Nakamura 0:a40b9a259b52 1235 return callback(e);
Osamu Nakamura 0:a40b9a259b52 1236 }
Osamu Nakamura 0:a40b9a259b52 1237 // if result is Promise object
Osamu Nakamura 0:a40b9a259b52 1238 if (_isObject(result) && typeof result.then === "function") {
Osamu Nakamura 0:a40b9a259b52 1239 result.then(function(value) {
Osamu Nakamura 0:a40b9a259b52 1240 callback(null, value);
Osamu Nakamura 0:a40b9a259b52 1241 })["catch"](function(err) {
Osamu Nakamura 0:a40b9a259b52 1242 callback(err.message ? err : new Error(err));
Osamu Nakamura 0:a40b9a259b52 1243 });
Osamu Nakamura 0:a40b9a259b52 1244 } else {
Osamu Nakamura 0:a40b9a259b52 1245 callback(null, result);
Osamu Nakamura 0:a40b9a259b52 1246 }
Osamu Nakamura 0:a40b9a259b52 1247 });
Osamu Nakamura 0:a40b9a259b52 1248 };
Osamu Nakamura 0:a40b9a259b52 1249
Osamu Nakamura 0:a40b9a259b52 1250 // Node.js
Osamu Nakamura 0:a40b9a259b52 1251 if (typeof module === 'object' && module.exports) {
Osamu Nakamura 0:a40b9a259b52 1252 module.exports = async;
Osamu Nakamura 0:a40b9a259b52 1253 }
Osamu Nakamura 0:a40b9a259b52 1254 // AMD / RequireJS
Osamu Nakamura 0:a40b9a259b52 1255 else if (typeof define === 'function' && define.amd) {
Osamu Nakamura 0:a40b9a259b52 1256 define([], function () {
Osamu Nakamura 0:a40b9a259b52 1257 return async;
Osamu Nakamura 0:a40b9a259b52 1258 });
Osamu Nakamura 0:a40b9a259b52 1259 }
Osamu Nakamura 0:a40b9a259b52 1260 // included directly via <script> tag
Osamu Nakamura 0:a40b9a259b52 1261 else {
Osamu Nakamura 0:a40b9a259b52 1262 root.async = async;
Osamu Nakamura 0:a40b9a259b52 1263 }
Osamu Nakamura 0:a40b9a259b52 1264
Osamu Nakamura 0:a40b9a259b52 1265 }());