123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- function isArray(arr) {
- return Object.prototype.toString.call(arr) === '[object Array]'
- }
- function foreach(arr, handler) {
- if (isArray(arr)) {
- for (var i = 0; i < arr.length; i++) {
- handler(arr[i])
- }
- } else handler(arr)
- }
- function D(fn) {
- var status = 'pending',
- doneFuncs = [],
- failFuncs = [],
- progressFuncs = [],
- resultArgs = null,
- promise = {
- done: function () {
- for (var i = 0; i < arguments.length; i++) {
- // skip any undefined or null arguments
- if (!arguments[i]) {
- continue
- }
- if (isArray(arguments[i])) {
- var arr = arguments[i]
- for (var j = 0; j < arr.length; j++) {
- // immediately call the function if the deferred has been resolved
- if (status === 'resolved') {
- arr[j].apply(this, resultArgs)
- }
- doneFuncs.push(arr[j])
- }
- } else {
- // immediately call the function if the deferred has been resolved
- if (status === 'resolved') {
- arguments[i].apply(this, resultArgs)
- }
- doneFuncs.push(arguments[i])
- }
- }
- return this
- },
- fail: function () {
- for (var i = 0; i < arguments.length; i++) {
- // skip any undefined or null arguments
- if (!arguments[i]) {
- continue
- }
- if (isArray(arguments[i])) {
- var arr = arguments[i]
- for (var j = 0; j < arr.length; j++) {
- // immediately call the function if the deferred has been resolved
- if (status === 'rejected') {
- arr[j].apply(this, resultArgs)
- }
- failFuncs.push(arr[j])
- }
- } else {
- // immediately call the function if the deferred has been resolved
- if (status === 'rejected') {
- arguments[i].apply(this, resultArgs)
- }
- failFuncs.push(arguments[i])
- }
- }
- return this
- },
- always: function () {
- return this.done.apply(this, arguments).fail.apply(this, arguments)
- },
- progress: function () {
- for (var i = 0; i < arguments.length; i++) {
- // skip any undefined or null arguments
- if (!arguments[i]) {
- continue
- }
- if (isArray(arguments[i])) {
- var arr = arguments[i]
- for (var j = 0; j < arr.length; j++) {
- // immediately call the function if the deferred has been resolved
- if (status === 'pending') {
- progressFuncs.push(arr[j])
- }
- }
- } else {
- // immediately call the function if the deferred has been resolved
- if (status === 'pending') {
- progressFuncs.push(arguments[i])
- }
- }
- }
- return this
- },
- then: function (done, fail, progress) {
- /*
- // fail callbacks
- if (arguments.length > 1 && arguments[1]) {
- this.fail(arguments[1])
- }
- // done callbacks
- if (arguments.length > 0 && arguments[0]) {
- this.done(arguments[0])
- }
- // notify callbacks
- if (arguments.length > 2 && arguments[2]) {
- this.progress(arguments[2])
- }
- return this
- */
- return D(function (def) {
- foreach(done, function (func) {
- // filter function
- if (typeof func === 'function') {
- deferred.done(function () {
- var returnval = func.apply(this, arguments)
- // if a new deferred/promise is returned, its state is passed to the current deferred/promise
- if (returnval && typeof returnval === 'function') {
- returnval.promise().then(def.resolve, def.reject, def.notify)
- } else {
- // if new return val is passed, it is passed to the piped done
- def.resolve(returnval)
- }
- })
- } else {
- deferred.done(def.resolve)
- }
- })
- foreach(fail, function (func) {
- if (typeof func === 'function') {
- deferred.fail(function () {
- var returnval = func.apply(this, arguments)
- if (returnval && typeof returnval === 'function') {
- returnval.promise().then(def.resolve, def.reject, def.notify)
- } else {
- def.reject(returnval)
- }
- })
- } else {
- deferred.fail(def.reject)
- }
- })
- }).promise()
- },
- catch: function () {
- for (var i = 0; i < arguments.length; i++) {
- // skip any undefined or null arguments
- if (!arguments[i]) {
- continue
- }
- if (isArray(arguments[i])) {
- var arr = arguments[i]
- for (var j = 0; j < arr.length; j++) {
- // immediately call the function if the deferred has been resolved
- if (status === 'rejected') {
- arr[j].apply(this, resultArgs)
- }
- failFuncs.push(arr[j])
- }
- } else {
- // immediately call the function if the deferred has been resolved
- if (status === 'rejected') {
- arguments[i].apply(this, resultArgs)
- }
- failFuncs.push(arguments[i])
- }
- }
- return this
- },
- promise: function (obj) {
- if (obj == null) {
- return promise
- } else {
- for (var i in promise) {
- obj[i] = promise[i]
- }
- return obj
- }
- },
- state: function () {
- return status
- },
- debug: function () {
- console.log('[debug]', doneFuncs, failFuncs, status)
- },
- isRejected: function () {
- return status === 'rejected'
- },
- isResolved: function () {
- return status === 'resolved'
- },
- pipe: function (done, fail, progress) {
- return D(function (def) {
- foreach(done, function (func) {
- // filter function
- if (typeof func === 'function') {
- deferred.done(function () {
- var returnval = func.apply(this, arguments)
- // if a new deferred/promise is returned, its state is passed to the current deferred/promise
- if (returnval && typeof returnval === 'function') {
- returnval.promise().then(def.resolve, def.reject, def.notify)
- } else {
- // if new return val is passed, it is passed to the piped done
- def.resolve(returnval)
- }
- })
- } else {
- deferred.done(def.resolve)
- }
- })
- foreach(fail, function (func) {
- if (typeof func === 'function') {
- deferred.fail(function () {
- var returnval = func.apply(this, arguments)
- if (returnval && typeof returnval === 'function') {
- returnval.promise().then(def.resolve, def.reject, def.notify)
- } else {
- def.reject(returnval)
- }
- })
- } else {
- deferred.fail(def.reject)
- }
- })
- }).promise()
- },
- },
- deferred = {
- resolveWith: function (context) {
- if (status === 'pending') {
- status = 'resolved'
- var args = (resultArgs = arguments.length > 1 ? arguments[1] : [])
- for (var i = 0; i < doneFuncs.length; i++) {
- doneFuncs[i].apply(context, args)
- }
- }
- return this
- },
- rejectWith: function (context) {
- if (status === 'pending') {
- status = 'rejected'
- var args = (resultArgs = arguments.length > 1 ? arguments[1] : [])
- for (var i = 0; i < failFuncs.length; i++) {
- failFuncs[i].apply(context, args)
- }
- }
- return this
- },
- notifyWith: function (context) {
- if (status === 'pending') {
- var args = (resultArgs = arguments.length > 1 ? arguments[1] : [])
- for (var i = 0; i < progressFuncs.length; i++) {
- progressFuncs[i].apply(context, args)
- }
- }
- return this
- },
- resolve: function () {
- return this.resolveWith(this, arguments)
- },
- reject: function () {
- return this.rejectWith(this, arguments)
- },
- notify: function () {
- return this.notifyWith(this, arguments)
- },
- resolveValue: function(val) {
- status = 'resolved'
- var args = (resultArgs = val == void 0 ? [] : [val])
- for (var i = 0; i < doneFuncs.length; i++) {
- doneFuncs[i].apply(this, args)
- }
- return this
- }
- }
- var obj = promise.promise(deferred)
- if (fn) {
- fn.apply(obj, [obj])
- }
- return obj
- }
- D.when = function () {
- if (arguments.length < 2) {
- var obj = arguments.length ? arguments[0] : undefined
- if (obj && typeof obj.isResolved === 'function' && typeof obj.isRejected === 'function') {
- return obj.promise()
- } else {
- return D().resolve(obj).promise()
- }
- } else {
- return (function (args) {
- var df = D(),
- size = args.length,
- done = 0,
- rp = new Array(size) // resolve params: params of each resolve, we need to track down them to be able to pass them in the correct order if the master needs to be resolved
- for (var i = 0; i < args.length; i++) {
- ;(function (j) {
- var obj = null
- if (args[j].done) {
- args[j]
- .done(function () {
- rp[j] = arguments.length < 2 ? arguments[0] : arguments
- if (++done == size) {
- df.resolve.apply(df, rp)
- }
- })
- .fail(function () {
- df.reject(arguments)
- })
- } else {
- obj = args[j]
- args[j] = new Deferred()
- args[j]
- .done(function () {
- rp[j] = arguments.length < 2 ? arguments[0] : arguments
- if (++done == size) {
- df.resolve.apply(df, rp)
- }
- })
- .fail(function () {
- df.reject(arguments)
- })
- .resolve(obj)
- }
- })(i)
- }
- return df.promise()
- })(arguments)
- }
- }
- export const Defer = D
- export default function () {
- return new D()
- }
|