PageRenderTime 41ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs//0.1.1/q.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 361 lines | 192 code | 38 blank | 131 comment | 22 complexity | 46c6098624f03f9a61e7fd43020121b6 MD5 | raw file
  1. // Tyler Close
  2. // Ported by Kris Kowal
  3. // Variation to illustrated ideas for improvements on the API.
  4. // * Deferred, Rejection, Reference instead of defer, reject, ref, and promise.
  5. // * Promise constructor that takes a descriptor and fallback.
  6. // * near has been changed to valueOf, and uses a valueOf operator instead
  7. // an undefined operator, to reduce special cases.
  8. // * variadic arguments are used internally where applicable (POST arguments
  9. // have not yet been altered.
  10. /*
  11. * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
  12. * at http://www.opensource.org/licenses/mit-license.html
  13. *
  14. * ref_send.js version: 2009-05-11
  15. */
  16. /*whatsupdoc*/
  17. // - the enclosure ensures that this module will function properly both as a
  18. // CommonJS module and as a script in the browser. In CommonJS, this module
  19. // exports the "Q" API. In the browser, this script creates a "Q" object in
  20. // global scope.
  21. // - the use of "undefined" on the enclosure is a micro-optmization for
  22. // compression systems, permitting every occurrence of the "undefined" keyword
  23. // bo be replaced with a single-character.
  24. (function (exports, undefined) {
  25. "use strict";
  26. // this provides an enqueue method in browsers, Narwhal, and NodeJS
  27. var enqueue;
  28. if (typeof setTimeout === "function") {
  29. enqueue = function (task) {
  30. setTimeout(task, 0);
  31. };
  32. } else {
  33. enqueue = require("event-loop").enqueue;
  34. }
  35. var print;
  36. if (typeof require !== "undefined") {
  37. try {
  38. print = require("system").print; // CommonJS
  39. } catch (exception) {
  40. print = require("sys").puts; // Node
  41. }
  42. } else if (typeof console !== "undefined") {
  43. print = function (message) {
  44. console.log(message);
  45. };
  46. } else {
  47. print = function () {}
  48. }
  49. /**
  50. * Performs a task in a future turn of the event loop.
  51. * @param {Function} task
  52. */
  53. exports.enqueue = enqueue;
  54. /**
  55. * Constructs a {promise, resolve} object.
  56. *
  57. * The resolver is a callback to invoke with a more resolved value for the
  58. * promise. To fulfill the promise, invoke the resolver with any value that is
  59. * not a function. To reject the promise, invoke the resolver with a rejection
  60. * object. To put the promise in the same state as another promise, invoke the
  61. * resolver with that other promise.
  62. */
  63. exports.defer = defer;
  64. function defer() {
  65. // if "pending" is an "Array", that indicates that the promise has not yet
  66. // been resolved. If it is "undefined", it has been resolved. Each
  67. // element of the pending array is itself an array of complete arguments to
  68. // forward to the resolved promise. We coerce the resolution value to a
  69. // promise using the ref promise because it handles both fully
  70. // resolved values and other promises gracefully.
  71. var pending = [], value;
  72. var promise = Object.create(Promise.prototype);
  73. promise.emit = function () {
  74. var args = Array.prototype.slice.call(arguments);
  75. if (pending) {
  76. pending.push(args);
  77. } else {
  78. forward.apply(undefined, [value].concat(args));
  79. }
  80. };
  81. var resolve = function (resolvedValue) {
  82. var i, ii, task;
  83. if (!pending)
  84. return;
  85. value = ref(resolvedValue);
  86. for (i = 0, ii = pending.length; i < ii; ++i) {
  87. forward.apply(undefined, [value].concat(pending[i]));
  88. }
  89. pending = undefined;
  90. };
  91. return {
  92. "promise": promise,
  93. "resolve": resolve,
  94. "reject": function (reason) {
  95. resolve(reject(reason));
  96. }
  97. };
  98. }
  99. /**
  100. * Constructs a Promise with a promise descriptor object and optional fallback
  101. * function. The descriptor contains methods like when(rejected), get(name),
  102. * put(name, value), post(name, args), delete(name), and valueOf(), which all
  103. * return either a value, a promise for a value, or a rejection. The fallback
  104. * accepts the operation name, a resolver, and any further arguments that would
  105. * have been forwarded to the appropriate method above had a method been
  106. * provided with the proper name. The API makes no guarantees about the nature
  107. * of the returned object, apart from that it is usable whereever promises are
  108. * bought and sold.
  109. */
  110. exports.Promise = Promise;
  111. function Promise(descriptor, fallback) {
  112. if (fallback === undefined) {
  113. fallback = function (op) {
  114. return reject("Promise does not support operation: " + op);
  115. };
  116. }
  117. var promise = Object.create(Promise.prototype);
  118. promise.emit = function (op, resolved /* ...args */) {
  119. var args = Array.prototype.slice.call(arguments, 2);
  120. var result;
  121. if (descriptor[op])
  122. result = descriptor[op].apply(descriptor, args);
  123. else
  124. result = fallback.apply(descriptor, arguments);
  125. if (resolved)
  126. return resolved(result);
  127. return result;
  128. };
  129. return promise;
  130. };
  131. Promise.prototype.toSource = function () {
  132. return this.toString();
  133. };
  134. Promise.prototype.toString = function () {
  135. return '[object Promise]';
  136. };
  137. Promise.prototype.valueOf = function () {
  138. return this.emit("valueOf");
  139. };
  140. /**
  141. * @returns whether the given object is a promise.
  142. * Otherwise it is a resolved value.
  143. */
  144. exports.isPromise = isPromise;
  145. function isPromise(object) {
  146. return object instanceof Promise;
  147. };
  148. /**
  149. * Constructs a rejected promise.
  150. * @param reason value describing the failure
  151. */
  152. exports.reject = reject;
  153. function reject(reason) {
  154. return Promise({
  155. "when": function (rejected) {
  156. return rejected ? rejected(reason) : reject(reason);
  157. }
  158. }, function fallback(op, resolved) {
  159. var rejection = reject(reason);
  160. return resolved ? resolved(rejection) : rejection;
  161. });
  162. }
  163. /**
  164. * Constructs a promise for an immediate reference.
  165. * @param value immediate reference
  166. */
  167. exports.ref = ref;
  168. function ref(object) {
  169. // If the object is already a Promise, return it directly. This enables
  170. // the ref function to both be used to created references from
  171. // objects, but to tolerably coerce non-promises to refs if they are
  172. // not already Promises.
  173. if (isPromise(object))
  174. return object;
  175. return Promise({
  176. "when": function (rejected) {
  177. return object;
  178. },
  179. "get": function (name) {
  180. return object[name];
  181. },
  182. "put": function (name, value) {
  183. object[name] = value;
  184. },
  185. "delete": function (name) {
  186. delete object[name];
  187. },
  188. "post": function (name, args) {
  189. return object[name].apply(object, args);
  190. },
  191. "valueOf": function () {
  192. return object;
  193. }
  194. });
  195. }
  196. /**
  197. * Constructs a promise method that can be used to safely observe resolution of
  198. * a promise for an arbitrarily named method like "propfind" in a future turn.
  199. *
  200. * "Method" constructs methods like "get(promise, name)" and "put(promise)".
  201. */
  202. exports.Method = Method;
  203. function Method (methodName) {
  204. return function (object) {
  205. var deferred = defer();
  206. var args = Array.prototype.slice.call(arguments, 1);
  207. forward.apply(undefined, [
  208. ref(object),
  209. methodName,
  210. deferred.resolve
  211. ].concat(args));
  212. return deferred.promise;
  213. };
  214. }
  215. /**
  216. * Registers an observer on a promise.
  217. *
  218. * Guarantees:
  219. *
  220. * 1. that resolved and rejected will be called only once.
  221. * 2. that either the resolved callback or the rejected callback will be
  222. * called, but not both.
  223. * 3. that resolved and rejected will not be called in this turn.
  224. *
  225. * @param value promise or immediate reference to observe
  226. * @param resolve function to be called with the resolved value
  227. * @param rejected function to be called with the rejection reason
  228. * @return promise for the return value from the invoked callback
  229. */
  230. exports.when = function (value, resolved, rejected) {
  231. var deferred = defer();
  232. var done = false; // ensure the untrusted promise makes at most a
  233. // single call to one of the callbacks
  234. forward(ref(value), "when", function (value) {
  235. if (done)
  236. return;
  237. done = true;
  238. deferred.resolve(ref(value).emit("when", resolved, rejected));
  239. }, function (reason) {
  240. if (done)
  241. return;
  242. done = true;
  243. deferred.resolve(rejected ? rejected(reason) : reject(reason));
  244. });
  245. return deferred.promise;
  246. };
  247. /**
  248. */
  249. exports.asap = function (value, resolved, rejected) {
  250. if (exports.isPromise(value)) {
  251. return exports.when(value, resolved, rejected);
  252. } else {
  253. return resolved(value);
  254. }
  255. };
  256. /**
  257. * Gets the value of a property in a future turn.
  258. * @param object promise or immediate reference for target object
  259. * @param name name of property to get
  260. * @return promise for the property value
  261. */
  262. exports.get = Method("get");
  263. /**
  264. * Sets the value of a property in a future turn.
  265. * @param object promise or immediate reference for object object
  266. * @param name name of property to set
  267. * @param value new value of property
  268. * @return promise for the return value
  269. */
  270. exports.put = Method("put");
  271. /**
  272. * Deletes a property in a future turn.
  273. * @param object promise or immediate reference for target object
  274. * @param name name of property to delete
  275. * @return promise for the return value
  276. */
  277. exports.del = Method("del");
  278. /**
  279. * Invokes a method in a future turn.
  280. * @param object promise or immediate reference for target object
  281. * @param name name of method to invoke
  282. * @param argv array of invocation arguments
  283. * @return promise for the return value
  284. */
  285. exports.post = Method("post");
  286. /**
  287. * Guarantees that the give promise resolves to a defined, non-null value.
  288. */
  289. exports.defined = function (value) {
  290. return exports.when(value, function (value) {
  291. if (value === undefined || value === null)
  292. return reject("Resolved undefined value: " + value);
  293. return value;
  294. });
  295. };
  296. /**
  297. * Throws an error with the given reason.
  298. */
  299. exports.error = function (reason) {
  300. if (!(reason instanceof Error))
  301. reason = new Error(reason);
  302. throw reason;
  303. };
  304. /*
  305. * Enqueues a promise operation for a future turn.
  306. */
  307. function forward(promise /*, op, resolved, ... */) {
  308. var args = Array.prototype.slice.call(arguments, 1);
  309. enqueue(function () {
  310. try {
  311. promise.emit.apply(promise, args);
  312. } catch (exception) {
  313. print(exception.stack || exception);
  314. }
  315. });
  316. }
  317. // Complete the closure: use either CommonJS exports or browser global Q object
  318. // for the exports internally.
  319. })(
  320. typeof exports !== "undefined" ?
  321. exports :
  322. this["/q"] = {}
  323. );