twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

map.js (5602B)


      1 "use strict";
      2 module.exports = function(Promise,
      3                           PromiseArray,
      4                           apiRejection,
      5                           tryConvertToPromise,
      6                           INTERNAL,
      7                           debug) {
      8 var util = require("./util");
      9 var tryCatch = util.tryCatch;
     10 var errorObj = util.errorObj;
     11 var async = Promise._async;
     12 
     13 function MappingPromiseArray(promises, fn, limit, _filter) {
     14     this.constructor$(promises);
     15     this._promise._captureStackTrace();
     16     var context = Promise._getContext();
     17     this._callback = util.contextBind(context, fn);
     18     this._preservedValues = _filter === INTERNAL
     19         ? new Array(this.length())
     20         : null;
     21     this._limit = limit;
     22     this._inFlight = 0;
     23     this._queue = [];
     24     async.invoke(this._asyncInit, this, undefined);
     25     if (util.isArray(promises)) {
     26         for (var i = 0; i < promises.length; ++i) {
     27             var maybePromise = promises[i];
     28             if (maybePromise instanceof Promise) {
     29                 maybePromise.suppressUnhandledRejections();
     30             }
     31         }
     32     }
     33 }
     34 util.inherits(MappingPromiseArray, PromiseArray);
     35 
     36 MappingPromiseArray.prototype._asyncInit = function() {
     37     this._init$(undefined, -2);
     38 };
     39 
     40 MappingPromiseArray.prototype._init = function () {};
     41 
     42 MappingPromiseArray.prototype._promiseFulfilled = function (value, index) {
     43     var values = this._values;
     44     var length = this.length();
     45     var preservedValues = this._preservedValues;
     46     var limit = this._limit;
     47 
     48     if (index < 0) {
     49         index = (index * -1) - 1;
     50         values[index] = value;
     51         if (limit >= 1) {
     52             this._inFlight--;
     53             this._drainQueue();
     54             if (this._isResolved()) return true;
     55         }
     56     } else {
     57         if (limit >= 1 && this._inFlight >= limit) {
     58             values[index] = value;
     59             this._queue.push(index);
     60             return false;
     61         }
     62         if (preservedValues !== null) preservedValues[index] = value;
     63 
     64         var promise = this._promise;
     65         var callback = this._callback;
     66         var receiver = promise._boundValue();
     67         promise._pushContext();
     68         var ret = tryCatch(callback).call(receiver, value, index, length);
     69         var promiseCreated = promise._popContext();
     70         debug.checkForgottenReturns(
     71             ret,
     72             promiseCreated,
     73             preservedValues !== null ? "Promise.filter" : "Promise.map",
     74             promise
     75         );
     76         if (ret === errorObj) {
     77             this._reject(ret.e);
     78             return true;
     79         }
     80 
     81         var maybePromise = tryConvertToPromise(ret, this._promise);
     82         if (maybePromise instanceof Promise) {
     83             maybePromise = maybePromise._target();
     84             var bitField = maybePromise._bitField;
     85             ;
     86             if (((bitField & 50397184) === 0)) {
     87                 if (limit >= 1) this._inFlight++;
     88                 values[index] = maybePromise;
     89                 maybePromise._proxy(this, (index + 1) * -1);
     90                 return false;
     91             } else if (((bitField & 33554432) !== 0)) {
     92                 ret = maybePromise._value();
     93             } else if (((bitField & 16777216) !== 0)) {
     94                 this._reject(maybePromise._reason());
     95                 return true;
     96             } else {
     97                 this._cancel();
     98                 return true;
     99             }
    100         }
    101         values[index] = ret;
    102     }
    103     var totalResolved = ++this._totalResolved;
    104     if (totalResolved >= length) {
    105         if (preservedValues !== null) {
    106             this._filter(values, preservedValues);
    107         } else {
    108             this._resolve(values);
    109         }
    110         return true;
    111     }
    112     return false;
    113 };
    114 
    115 MappingPromiseArray.prototype._drainQueue = function () {
    116     var queue = this._queue;
    117     var limit = this._limit;
    118     var values = this._values;
    119     while (queue.length > 0 && this._inFlight < limit) {
    120         if (this._isResolved()) return;
    121         var index = queue.pop();
    122         this._promiseFulfilled(values[index], index);
    123     }
    124 };
    125 
    126 MappingPromiseArray.prototype._filter = function (booleans, values) {
    127     var len = values.length;
    128     var ret = new Array(len);
    129     var j = 0;
    130     for (var i = 0; i < len; ++i) {
    131         if (booleans[i]) ret[j++] = values[i];
    132     }
    133     ret.length = j;
    134     this._resolve(ret);
    135 };
    136 
    137 MappingPromiseArray.prototype.preservedValues = function () {
    138     return this._preservedValues;
    139 };
    140 
    141 function map(promises, fn, options, _filter) {
    142     if (typeof fn !== "function") {
    143         return apiRejection("expecting a function but got " + util.classString(fn));
    144     }
    145 
    146     var limit = 0;
    147     if (options !== undefined) {
    148         if (typeof options === "object" && options !== null) {
    149             if (typeof options.concurrency !== "number") {
    150                 return Promise.reject(
    151                     new TypeError("'concurrency' must be a number but it is " +
    152                                     util.classString(options.concurrency)));
    153             }
    154             limit = options.concurrency;
    155         } else {
    156             return Promise.reject(new TypeError(
    157                             "options argument must be an object but it is " +
    158                              util.classString(options)));
    159         }
    160     }
    161     limit = typeof limit === "number" &&
    162         isFinite(limit) && limit >= 1 ? limit : 0;
    163     return new MappingPromiseArray(promises, fn, limit, _filter).promise();
    164 }
    165 
    166 Promise.prototype.map = function (fn, options) {
    167     return map(this, fn, options, null);
    168 };
    169 
    170 Promise.map = function (promises, fn, options, _filter) {
    171     return map(promises, fn, options, _filter);
    172 };
    173 
    174 
    175 };