1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
// Promise aware Array's find
// Additionally differs from some that it returns *first in order* item that matches constraint
"use strict";
var assign = require("es5-ext/object/assign")
, isValue = require("es5-ext/object/is-value")
, ensureValue = require("es5-ext/object/valid-value")
, callable = require("es5-ext/object/valid-callable")
, toNaturalNumber = require("es5-ext/number/to-pos-integer")
, deferred = require("../../deferred")
, isPromise = require("../../is-promise")
, assimilate = require("../../assimilate");
var call = Function.prototype.call, resolve = deferred.resolve, Find;
Find = function (list, cb, context) {
this.list = list;
this.cb = cb;
this.context = context;
this.length = toNaturalNumber(list.length);
while (this.current < this.length) {
if (this.current in list) {
assign(this, deferred());
this.processCb = this.processCb.bind(this);
this.process();
return this.promise;
}
++this.current;
}
return resolve(undefined);
};
Find.prototype = {
current: 0,
process: function () {
var value = assimilate(this.list[this.current]);
if (isPromise(value)) {
if (!value.resolved) {
value.done(this.processCb, this.reject);
return;
}
if (value.failed) {
this.reject(value.value);
return;
}
value = value.value;
}
this.processCb(value);
},
processCb: function (listValue) {
var value;
if (this.cb) {
try {
value = call.call(this.cb, this.context, listValue, this.current, this.list);
} catch (e) {
this.reject(e);
return;
}
value = assimilate(value);
if (isPromise(value)) {
if (!value.resolved) {
value.done(this.processValue.bind(this, listValue), this.reject);
return;
}
if (value.failed) {
this.reject(value.value);
return;
}
value = value.value;
}
} else {
value = listValue;
}
this.processValue(listValue, value);
},
processValue: function (listValue, value) {
if (value) {
this.resolve(listValue);
return;
}
while (++this.current < this.length) {
if (this.current in this.list) {
this.process();
return;
}
}
this.resolve(undefined);
}
};
module.exports = function (cb/*, thisArg*/) {
ensureValue(this);
if (isValue(cb)) callable(cb);
return new Find(this, cb, arguments[1]);
};
|