deferred.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Zepto.js
  2. // (c) 2010-2016 Thomas Fuchs
  3. // Zepto.js may be freely distributed under the MIT license.
  4. //
  5. // Some code (c) 2005, 2013 jQuery Foundation, Inc. and other contributors
  6. ;(function($){
  7. var slice = Array.prototype.slice
  8. function Deferred(func) {
  9. var tuples = [
  10. // action, add listener, listener list, final state
  11. [ "resolve", "done", $.Callbacks({once:1, memory:1}), "resolved" ],
  12. [ "reject", "fail", $.Callbacks({once:1, memory:1}), "rejected" ],
  13. [ "notify", "progress", $.Callbacks({memory:1}) ]
  14. ],
  15. state = "pending",
  16. promise = {
  17. state: function() {
  18. return state
  19. },
  20. always: function() {
  21. deferred.done(arguments).fail(arguments)
  22. return this
  23. },
  24. then: function(/* fnDone [, fnFailed [, fnProgress]] */) {
  25. var fns = arguments
  26. return Deferred(function(defer){
  27. $.each(tuples, function(i, tuple){
  28. var fn = $.isFunction(fns[i]) && fns[i]
  29. deferred[tuple[1]](function(){
  30. var returned = fn && fn.apply(this, arguments)
  31. if (returned && $.isFunction(returned.promise)) {
  32. returned.promise()
  33. .done(defer.resolve)
  34. .fail(defer.reject)
  35. .progress(defer.notify)
  36. } else {
  37. var context = this === promise ? defer.promise() : this,
  38. values = fn ? [returned] : arguments
  39. defer[tuple[0] + "With"](context, values)
  40. }
  41. })
  42. })
  43. fns = null
  44. }).promise()
  45. },
  46. promise: function(obj) {
  47. return obj != null ? $.extend( obj, promise ) : promise
  48. }
  49. },
  50. deferred = {}
  51. $.each(tuples, function(i, tuple){
  52. var list = tuple[2],
  53. stateString = tuple[3]
  54. promise[tuple[1]] = list.add
  55. if (stateString) {
  56. list.add(function(){
  57. state = stateString
  58. }, tuples[i^1][2].disable, tuples[2][2].lock)
  59. }
  60. deferred[tuple[0]] = function(){
  61. deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments)
  62. return this
  63. }
  64. deferred[tuple[0] + "With"] = list.fireWith
  65. })
  66. promise.promise(deferred)
  67. if (func) func.call(deferred, deferred)
  68. return deferred
  69. }
  70. $.when = function(sub) {
  71. var resolveValues = slice.call(arguments),
  72. len = resolveValues.length,
  73. i = 0,
  74. remain = len !== 1 || (sub && $.isFunction(sub.promise)) ? len : 0,
  75. deferred = remain === 1 ? sub : Deferred(),
  76. progressValues, progressContexts, resolveContexts,
  77. updateFn = function(i, ctx, val){
  78. return function(value){
  79. ctx[i] = this
  80. val[i] = arguments.length > 1 ? slice.call(arguments) : value
  81. if (val === progressValues) {
  82. deferred.notifyWith(ctx, val)
  83. } else if (!(--remain)) {
  84. deferred.resolveWith(ctx, val)
  85. }
  86. }
  87. }
  88. if (len > 1) {
  89. progressValues = new Array(len)
  90. progressContexts = new Array(len)
  91. resolveContexts = new Array(len)
  92. for ( ; i < len; ++i ) {
  93. if (resolveValues[i] && $.isFunction(resolveValues[i].promise)) {
  94. resolveValues[i].promise()
  95. .done(updateFn(i, resolveContexts, resolveValues))
  96. .fail(deferred.reject)
  97. .progress(updateFn(i, progressContexts, progressValues))
  98. } else {
  99. --remain
  100. }
  101. }
  102. }
  103. if (!remain) deferred.resolveWith(resolveContexts, resolveValues)
  104. return deferred.promise()
  105. }
  106. $.Deferred = Deferred
  107. })(Zepto)