1 | 'use strict';
|
2 |
|
3 | function isPromise(obj) {
|
4 | return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
|
5 | }
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | var runAsync = module.exports = function (func, cb) {
|
20 | cb = cb || function () {};
|
21 |
|
22 | return function () {
|
23 |
|
24 | var args = arguments;
|
25 |
|
26 | var promise = new Promise(function (resolve, reject) {
|
27 | var resolved = false;
|
28 | const wrappedResolve = function (value) {
|
29 | if (resolved) {
|
30 | console.warn('Run-async promise already resolved.')
|
31 | }
|
32 | resolved = true;
|
33 | resolve(value);
|
34 | }
|
35 |
|
36 | var rejected = false;
|
37 | const wrappedReject = function (value) {
|
38 | if (rejected) {
|
39 | console.warn('Run-async promise already rejected.')
|
40 | }
|
41 | rejected = true;
|
42 | reject(value);
|
43 | }
|
44 |
|
45 | var usingCallback = false;
|
46 | var callbackConflict = false;
|
47 | var contextEnded = false;
|
48 |
|
49 | var answer = func.apply({
|
50 | async: function () {
|
51 | if (contextEnded) {
|
52 | console.warn('Run-async async() called outside a valid run-async context, callback will be ignored.');
|
53 | return function() {};
|
54 | }
|
55 | if (callbackConflict) {
|
56 | console.warn('Run-async wrapped function (async) returned a promise.\nCalls to async() callback can have unexpected results.');
|
57 | }
|
58 | usingCallback = true;
|
59 | return function (err, value) {
|
60 | if (err) {
|
61 | wrappedReject(err);
|
62 | } else {
|
63 | wrappedResolve(value);
|
64 | }
|
65 | };
|
66 | }
|
67 | }, Array.prototype.slice.call(args));
|
68 |
|
69 | if (usingCallback) {
|
70 | if (isPromise(answer)) {
|
71 | console.warn('Run-async wrapped function (sync) returned a promise but async() callback must be executed to resolve.');
|
72 | }
|
73 | } else {
|
74 | if (isPromise(answer)) {
|
75 | callbackConflict = true;
|
76 | answer.then(wrappedResolve, wrappedReject);
|
77 | } else {
|
78 | wrappedResolve(answer);
|
79 | }
|
80 | }
|
81 | contextEnded = true;
|
82 | });
|
83 |
|
84 | promise.then(cb.bind(null, null), cb);
|
85 |
|
86 | return promise;
|
87 | }
|
88 | };
|
89 |
|
90 | runAsync.cb = function (func, cb) {
|
91 | return runAsync(function () {
|
92 | var args = Array.prototype.slice.call(arguments);
|
93 | if (args.length === func.length - 1) {
|
94 | args.push(this.async());
|
95 | }
|
96 | return func.apply(this, args);
|
97 | }, cb);
|
98 | };
|