You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
6.2 KiB

  1. /*!
  2. * Module dependencies
  3. */
  4. var MPromise = require('mpromise');
  5. /**
  6. * Promise constructor.
  7. *
  8. * Promises are returned from executed queries. Example:
  9. *
  10. * var query = Candy.find({ bar: true });
  11. * var promise = query.exec();
  12. *
  13. * @param {Function} fn a function which will be called when the promise is resolved that accepts `fn(err, ...){}` as signature
  14. * @inherits mpromise https://github.com/aheckmann/mpromise
  15. * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
  16. * @event `err`: Emits when the promise is rejected
  17. * @event `complete`: Emits when the promise is fulfilled
  18. * @api public
  19. */
  20. function Promise (fn) {
  21. MPromise.call(this, fn);
  22. }
  23. /*!
  24. * Inherit from mpromise
  25. */
  26. Promise.prototype = Object.create(MPromise.prototype, {
  27. constructor: {
  28. value: Promise
  29. , enumerable: false
  30. , writable: true
  31. , configurable: true
  32. }
  33. });
  34. /*!
  35. * Override event names for backward compatibility.
  36. */
  37. Promise.SUCCESS = 'complete';
  38. Promise.FAILURE = 'err';
  39. /**
  40. * Adds `listener` to the `event`.
  41. *
  42. * If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event.
  43. *
  44. * @see mpromise#on https://github.com/aheckmann/mpromise#on
  45. * @method on
  46. * @memberOf Promise
  47. * @param {String} event
  48. * @param {Function} listener
  49. * @return {Promise} this
  50. * @api public
  51. */
  52. /**
  53. * Rejects this promise with `reason`.
  54. *
  55. * If the promise has already been fulfilled or rejected, not action is taken.
  56. *
  57. * @see mpromise#reject https://github.com/aheckmann/mpromise#reject
  58. * @method reject
  59. * @memberOf Promise
  60. * @param {Object|String|Error} reason
  61. * @return {Promise} this
  62. * @api public
  63. */
  64. /**
  65. * Rejects this promise with `err`.
  66. *
  67. * If the promise has already been fulfilled or rejected, not action is taken.
  68. *
  69. * Differs from [#reject](#promise_Promise-reject) by first casting `err` to an `Error` if it is not `instanceof Error`.
  70. *
  71. * @api public
  72. * @param {Error|String} err
  73. * @return {Promise} this
  74. */
  75. Promise.prototype.error = function (err) {
  76. if (!(err instanceof Error)) err = new Error(err);
  77. return this.reject(err);
  78. }
  79. /**
  80. * Resolves this promise to a rejected state if `err` is passed or a fulfilled state if no `err` is passed.
  81. *
  82. * If the promise has already been fulfilled or rejected, not action is taken.
  83. *
  84. * `err` will be cast to an Error if not already instanceof Error.
  85. *
  86. * _NOTE: overrides [mpromise#resolve](https://github.com/aheckmann/mpromise#resolve) to provide error casting._
  87. *
  88. * @param {Error} [err] error or null
  89. * @param {Object} [val] value to fulfill the promise with
  90. * @api public
  91. */
  92. Promise.prototype.resolve = function (err, val) {
  93. if (err) return this.error(err);
  94. return this.fulfill(val);
  95. }
  96. /**
  97. * Adds a single function as a listener to both err and complete.
  98. *
  99. * It will be executed with traditional node.js argument position when the promise is resolved.
  100. *
  101. * promise.addBack(function (err, args...) {
  102. * if (err) return handleError(err);
  103. * console.log('success');
  104. * })
  105. *
  106. * Alias of [mpromise#onResolve](https://github.com/aheckmann/mpromise#onresolve).
  107. *
  108. * @method addBack
  109. * @param {Function} listener
  110. * @return {Promise} this
  111. */
  112. Promise.prototype.addBack = Promise.prototype.onResolve;
  113. /**
  114. * Fulfills this promise with passed arguments.
  115. *
  116. * Alias of [mpromise#fulfill](https://github.com/aheckmann/mpromise#fulfill).
  117. *
  118. * @method complete
  119. * @param {any} args
  120. * @api public
  121. */
  122. Promise.prototype.complete = MPromise.prototype.fulfill;
  123. /**
  124. * Adds a listener to the `complete` (success) event.
  125. *
  126. * Alias of [mpromise#onFulfill](https://github.com/aheckmann/mpromise#onfulfill).
  127. *
  128. * @method addCallback
  129. * @param {Function} listener
  130. * @return {Promise} this
  131. * @api public
  132. */
  133. Promise.prototype.addCallback = Promise.prototype.onFulfill;
  134. /**
  135. * Adds a listener to the `err` (rejected) event.
  136. *
  137. * Alias of [mpromise#onReject](https://github.com/aheckmann/mpromise#onreject).
  138. *
  139. * @method addErrback
  140. * @param {Function} listener
  141. * @return {Promise} this
  142. * @api public
  143. */
  144. Promise.prototype.addErrback = Promise.prototype.onReject;
  145. /**
  146. * Creates a new promise and returns it. If `onFulfill` or `onReject` are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.
  147. *
  148. * Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification.
  149. *
  150. * ####Example:
  151. *
  152. * var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();
  153. * promise.then(function (meetups) {
  154. * var ids = meetups.map(function (m) {
  155. * return m._id;
  156. * });
  157. * return People.find({ meetups: { $in: ids }).exec();
  158. * }).then(function (people) {
  159. * if (people.length < 10000) {
  160. * throw new Error('Too few people!!!');
  161. * } else {
  162. * throw new Error('Still need more people!!!');
  163. * }
  164. * }).then(null, function (err) {
  165. * assert.ok(err instanceof Error);
  166. * });
  167. *
  168. * @see promises-A+ https://github.com/promises-aplus/promises-spec
  169. * @see mpromise#then https://github.com/aheckmann/mpromise#then
  170. * @method then
  171. * @memberOf Promise
  172. * @param {Function} onFulFill
  173. * @param {Function} onReject
  174. * @return {Promise} newPromise
  175. */
  176. /**
  177. * Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught.
  178. *
  179. * ####Example:
  180. *
  181. * var p = new Promise;
  182. * p.then(function(){ throw new Error('shucks') });
  183. * setTimeout(function () {
  184. * p.fulfill();
  185. * // error was caught and swallowed by the promise returned from
  186. * // p.then(). we either have to always register handlers on
  187. * // the returned promises or we can do the following...
  188. * }, 10);
  189. *
  190. * // this time we use .end() which prevents catching thrown errors
  191. * var p = new Promise;
  192. * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--
  193. * setTimeout(function () {
  194. * p.fulfill(); // throws "shucks"
  195. * }, 10);
  196. *
  197. * @api public
  198. * @see mpromise#end https://github.com/aheckmann/mpromise#end
  199. * @method end
  200. * @memberOf Promise
  201. */
  202. /*!
  203. * expose
  204. */
  205. module.exports = Promise;