core.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. 'use strict';
  2. var asap = require('asap')
  3. module.exports = Promise;
  4. function Promise(fn) {
  5. if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new')
  6. if (typeof fn !== 'function') throw new TypeError('not a function')
  7. var state = null
  8. var value = null
  9. var deferreds = []
  10. var self = this
  11. this.then = function(onFulfilled, onRejected) {
  12. return new self.constructor(function(resolve, reject) {
  13. handle(new Handler(onFulfilled, onRejected, resolve, reject))
  14. })
  15. }
  16. function handle(deferred) {
  17. if (state === null) {
  18. deferreds.push(deferred)
  19. return
  20. }
  21. asap(function() {
  22. var cb = state ? deferred.onFulfilled : deferred.onRejected
  23. if (cb === null) {
  24. (state ? deferred.resolve : deferred.reject)(value)
  25. return
  26. }
  27. var ret
  28. try {
  29. ret = cb(value)
  30. }
  31. catch (e) {
  32. deferred.reject(e)
  33. return
  34. }
  35. deferred.resolve(ret)
  36. })
  37. }
  38. function resolve(newValue) {
  39. try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
  40. if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
  41. if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
  42. var then = newValue.then
  43. if (typeof then === 'function') {
  44. doResolve(then.bind(newValue), resolve, reject)
  45. return
  46. }
  47. }
  48. state = true
  49. value = newValue
  50. finale()
  51. } catch (e) { reject(e) }
  52. }
  53. function reject(newValue) {
  54. state = false
  55. value = newValue
  56. finale()
  57. }
  58. function finale() {
  59. for (var i = 0, len = deferreds.length; i < len; i++)
  60. handle(deferreds[i])
  61. deferreds = null
  62. }
  63. doResolve(fn, resolve, reject)
  64. }
  65. function Handler(onFulfilled, onRejected, resolve, reject){
  66. this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
  67. this.onRejected = typeof onRejected === 'function' ? onRejected : null
  68. this.resolve = resolve
  69. this.reject = reject
  70. }
  71. /**
  72. * Take a potentially misbehaving resolver function and make sure
  73. * onFulfilled and onRejected are only called once.
  74. *
  75. * Makes no guarantees about asynchrony.
  76. */
  77. function doResolve(fn, onFulfilled, onRejected) {
  78. var done = false;
  79. try {
  80. fn(function (value) {
  81. if (done) return
  82. done = true
  83. onFulfilled(value)
  84. }, function (reason) {
  85. if (done) return
  86. done = true
  87. onRejected(reason)
  88. })
  89. } catch (ex) {
  90. if (done) return
  91. done = true
  92. onRejected(ex)
  93. }
  94. }