| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- /*!
- * async.js
- * Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>
- * MIT Licensed
- */
- define(function(require, exports, module) {
- var STOP = exports.STOP = {}
- exports.Generator = function(source) {
- if (typeof source == "function")
- this.source = {
- next: source
- }
- else
- this.source = source
- }
- ;(function() {
- this.next = function(callback) {
- this.source.next(callback)
- }
- this.map = function(mapper) {
- if (!mapper)
- return this
-
- mapper = makeAsync(1, mapper)
-
- var source = this.source
- this.next = function(callback) {
- source.next(function(err, value) {
- if (err)
- callback(err)
- else {
- mapper(value, function(err, value) {
- if (err)
- callback(err)
- else
- callback(null, value)
- })
- }
- })
- }
- return new this.constructor(this)
- }
-
- this.filter = function(filter) {
- if (!filter)
- return this
-
- filter = makeAsync(1, filter)
-
- var source = this.source
- this.next = function(callback) {
- source.next(function handler(err, value) {
- if (err)
- callback(err)
- else {
- filter(value, function(err, takeIt) {
- if (err)
- callback(err)
- else if (takeIt)
- callback(null, value)
- else
- source.next(handler)
- })
- }
- })
- }
- return new this.constructor(this)
- }
- this.slice = function(begin, end) {
- var count = -1
- if (!end || end < 0)
- var end = Infinity
-
- var source = this.source
- this.next = function(callback) {
- source.next(function handler(err, value) {
- count++
- if (err)
- callback(err)
- else if (count >= begin && count < end)
- callback(null, value)
- else if (count >= end)
- callback(STOP)
- else
- source.next(handler)
- })
- }
- return new this.constructor(this)
- }
-
- this.reduce = function(reduce, initialValue) {
- reduce = makeAsync(3, reduce)
- var index = 0
- var done = false
- var previousValue = initialValue
-
- var source = this.source
- this.next = function(callback) {
- if (done)
- return callback(STOP)
- if (initialValue === undefined) {
- source.next(function(err, currentValue) {
- if (err)
- return callback(err, previousValue)
-
- previousValue = currentValue
- reduceAll()
- })
- }
- else
- reduceAll()
- function reduceAll() {
- source.next(function handler(err, currentValue) {
- if (err) {
- done = true
- if (err == STOP)
- return callback(null, previousValue)
- else
- return(err)
- }
- reduce(previousValue, currentValue, index++, function(err, value) {
- previousValue = value
- source.next(handler)
- })
- })
- }
- }
- return new this.constructor(this)
- }
-
- this.forEach =
- this.each = function(fn) {
- fn = makeAsync(1, fn)
-
- var source = this.source
- this.next = function(callback) {
- source.next(function handler(err, value) {
- if (err)
- callback(err)
- else {
- fn(value, function(err) {
- callback(err, value)
- })
- }
- })
- }
- return new this.constructor(this)
- }
-
- this.some = function(condition) {
- condition = makeAsync(1, condition)
-
- var source = this.source
- var done = false
- this.next = function(callback) {
- if (done)
- return callback(STOP)
-
- source.next(function handler(err, value) {
- if (err)
- return callback(err)
-
- condition(value, function(err, result) {
- if (err) {
- done = true
- if (err == STOP)
- callback(null, false)
- else
- callback(err)
- }
- else if (result) {
- done = true
- callback(null, true)
- }
- else
- source.next(handler)
- })
- })
- }
- return new this.constructor(this)
- }
-
- this.every = function(condition) {
- condition = makeAsync(1, condition)
-
- var source = this.source
- var done = false
- this.next = function(callback) {
- if (done)
- return callback(STOP)
-
- source.next(function handler(err, value) {
- if (err)
- return callback(err)
-
- condition(value, function(err, result) {
- if (err) {
- done = true
- if (err == STOP)
- callback(null, true)
- else
- callback(err)
- }
- else if (!result) {
- done = true
- callback(null, false)
- }
- else
- source.next(handler)
- })
- })
- }
- return new this.constructor(this)
- }
-
- this.call = function(context) {
- var source = this.source
- return this.map(function(fn, next) {
- fn = makeAsync(0, fn, context)
- fn.call(context, function(err, value) {
- next(err, value)
- })
- })
- }
-
- this.concat = function(generator) {
- var generators = [this]
- generators.push.apply(generators, arguments)
- var index = 0
- var source = generators[index++]
-
- return new this.constructor(function(callback) {
- source.next(function handler(err, value) {
- if (err) {
- if (err == STOP) {
- source = generators[index++]
- if (!source)
- return callback(STOP)
- else
- return source.next(handler)
- }
- else
- return callback(err)
- }
- else
- return callback(null, value)
- })
- })
- }
-
- this.zip = function(generator) {
- var generators = [this]
- generators.push.apply(generators, arguments)
-
- return new this.constructor(function(callback) {
- exports.list(generators)
- .map(function(gen, next) {
- gen.next(next)
- })
- .toArray(callback)
- })
- }
-
- this.expand = function(inserter, constructor) {
- if (!inserter)
- return this
-
- var inserter = makeAsync(1, inserter)
- var constructor = constructor || this.constructor
- var source = this.source;
- var spliced = null;
-
- return new constructor(function next(callback) {
- if (!spliced) {
- source.next(function(err, value) {
- if (err)
- return callback(err)
-
- inserter(value, function(err, toInsert) {
- if (err)
- return callback(err)
-
- spliced = toInsert
- next(callback)
- })
- })
- }
- else {
- spliced.next(function(err, value) {
- if (err == STOP) {
- spliced = null
- return next(callback)
- }
- else if (err)
- return callback(err)
-
- callback(err, value)
- })
- }
- })
- }
- this.sort = function(compare) {
- var self = this
- var arrGen
- this.next = function(callback) {
- if (arrGen)
- return arrGen.next(callback)
- self.toArray(function(err, arr) {
- if (err)
- callback(err)
- else {
- arrGen = exports.list(arr.sort(compare))
- arrGen.next(callback)
- }
- })
- }
- return new this.constructor(this)
- }
- this.join = function(separator) {
- return this.$arrayOp(Array.prototype.join, separator !== undefined ? [separator] : null)
- }
-
- this.reverse = function() {
- return this.$arrayOp(Array.prototype.reverse)
- }
-
- this.$arrayOp = function(arrayMethod, args) {
- var self = this
- var i = 0
- this.next = function(callback) {
- if (i++ > 0)
- return callback(STOP)
-
- self.toArray(function(err, arr) {
- if (err)
- callback(err, "")
- else {
- if (args)
- callback(null, arrayMethod.apply(arr, args))
- else
- callback(null, arrayMethod.call(arr))
- }
- })
- }
- return new this.constructor(this)
-
- }
-
- this.end = function(breakOnError, callback) {
- if (!callback) {
- callback = arguments[0]
- breakOnError = true
- }
- var source = this.source
- var last
- var lastError
- source.next(function handler(err, value) {
- if (err) {
- if (err == STOP)
- callback && callback(lastError, last)
- else if (!breakOnError) {
- lastError = err
- source.next(handler)
- }
- else
- callback && callback(err, value)
- }
- else {
- last = value
- source.next(handler)
- }
- })
- }
- this.toArray = function(breakOnError, callback) {
- if (!callback) {
- callback = arguments[0]
- breakOnError = true
- }
-
- var values = []
- var errors = []
- var source = this.source
-
- source.next(function handler(err, value) {
- if (err) {
- if (err == STOP) {
- if (breakOnError)
- return callback(null, values)
- else {
- errors.length = values.length
- return callback(errors, values)
- }
- }
- else {
- if (breakOnError)
- return callback(err)
- else
- errors[values.length] = err
- }
- }
- values.push(value)
- source.next(handler)
- })
- }
- }).call(exports.Generator.prototype)
- var makeAsync = exports.makeAsync = function(args, fn, context) {
- if (fn.length > args)
- return fn
- else {
- return function() {
- var value
- var next = arguments[args]
- try {
- value = fn.apply(context || this, arguments)
- } catch(e) {
- return next(e)
- }
- next(null, value)
- }
- }
- }
- exports.list = function(arr, construct) {
- var construct = construct || exports.Generator
- var i = 0
- var len = arr.length
-
- return new construct(function(callback) {
- if (i < len)
- callback(null, arr[i++])
- else
- callback(STOP)
- })
- }
- exports.values = function(map, construct) {
- var values = []
- for (var key in map)
- values.push(map[key])
-
- return exports.list(values, construct)
- }
- exports.keys = function(map, construct) {
- var keys = []
- for (var key in map)
- keys.push(key)
-
- return exports.list(keys, construct)
- }
- /*
- * range([start,] stop[, step]) -> generator of integers
- *
- * Return a generator containing an arithmetic progression of integers.
- * range(i, j) returns [i, i+1, i+2, ..., j-1] start (!) defaults to 0.
- * When step is given, it specifies the increment (or decrement).
- */
- exports.range = function(start, stop, step, construct) {
- var construct = construct || exports.Generator
- start = start || 0
- step = step || 1
-
- if (stop === undefined || stop === null)
- stop = step > 0 ? Infinity : -Infinity
-
- var value = start
-
- return new construct(function(callback) {
- if (step > 0 && value >= stop || step < 0 && value <= stop)
- callback(STOP)
- else {
- var current = value
- value += step
- callback(null, current)
- }
- })
- }
- exports.concat = function(first, varargs) {
- if (arguments.length > 1)
- return first.concat.apply(first, Array.prototype.slice.call(arguments, 1))
- else
- return first
- }
- exports.zip = function(first, varargs) {
- if (arguments.length > 1)
- return first.zip.apply(first, Array.prototype.slice.call(arguments, 1))
- else
- return first.map(function(item, next) {
- next(null, [item])
- })
- }
- exports.plugin = function(members, constructors) {
- if (members) {
- for (var key in members) {
- exports.Generator.prototype[key] = members[key]
- }
- }
- if (constructors) {
- for (var key in constructors) {
- exports[key] = constructors[key]
- }
- }
- }
- })
|