Skip to content

Commit

Permalink
Rename exec() -> run() + fix initial promise to run async
Browse files Browse the repository at this point in the history
  • Loading branch information
i20 committed Nov 19, 2019
1 parent 725f581 commit d632c95
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 72 deletions.
102 changes: 51 additions & 51 deletions Promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var nextTick = typeof process === 'object' && process.nextTick ? function (callb
process.nextTick(callback, param);
} : _global.postMessage ? (function () { // Otherwise try using window messaging that is still pretty fast

var messageType = 'i20-promise-job';
var messageType = 'promise-job';
var pool = [];
var i = -1;

Expand Down Expand Up @@ -63,46 +63,68 @@ function noopReject (error) {

function Promise (_executor) {

// Private vars

var self = this;

var _state = STATE_PENDING;
var _value;
var _queue = [];
var _watchers = [];

// Privileged methods
// Private methods

function _solver (nextState) {

return function (value) {

// Prevent multiple calls to resolve and reject inside executor, a promise is solved only once
if (_state !== STATE_RUNNING) return;

_state = nextState;
_value = value;

var next;
while (next = _queue.shift())
next.run();
};
}

// Privileged public methods
// https://crockford.com/javascript/private.html

self.execute = function () {
self.run = function () {

// Prevent re-executing a promise
if (_state !== STATE_PENDING) return;
nextTick(function () {

_state = STATE_RUNNING;
// Prevent re-executing a promise
if (_state !== STATE_PENDING) return;

try {
_executor( _solver(STATE_RESOLVED), _solver(STATE_REJECTED), function (notification) {
_state = STATE_RUNNING;

// Stop notifications as soon as promise is solved
// Useful when being notified by raced promises via Promise.race
if (_state !== STATE_RUNNING) return;
try {
_executor( _solver(STATE_RESOLVED), _solver(STATE_REJECTED), function (notification) {

for (var i = 0; i < _watchers.length; i++)
nextTick(_watchers[i], notification);
});
}
// Handle throw in executor as a reject call
catch (error) {
_solver(STATE_REJECTED)(error);
}
// Stop notifications as soon as promise is solved
// Useful when being notified by raced promises via Promise.race
if (_state !== STATE_RUNNING) return;

for (var i = 0; i < _watchers.length; i++)
nextTick(_watchers[i], notification);
});
}
// Handle throw in executor as a reject call
catch (error) {
_solver(STATE_REJECTED)(error);
}
});

return self;
};

self.then = function (resolve, reject, notify) {

if (notify)
_watchers.push(notify);
if (notify) _watchers.push(notify);

var promise = new Promise(function (nextResolve, nextReject, nextNotify) {

Expand All @@ -126,41 +148,19 @@ function Promise (_executor) {
else (success ? nextResolve : nextReject)(result);
});

// Promise is not solved yet
// Enqueue a child promise that will be executed when current finishes
// Parent promise is not solved yet
// Enqueue a child promise that will be executed when parent solves
if (_state < STATE_RESOLVED) _queue.push(promise);

// Promise has already been solved at binding time
else nextTick(function () {
promise.execute();
});
// Else parent promise has already been solved at binding time and child promise should have execute too
else promise.run();

return promise;
};

self.getState = function () {
return _state;
};

// Private methods

function _solver (nextState) {

return function (value) {

// Prevent multiple calls to resolve and reject inside executor, a promise is solved only once
if (_state !== STATE_RUNNING) return;

_state = nextState;
_value = value;

while ( _queue.length ) {
nextTick(function (next) {
next.execute();
}, _queue.shift());
}
};
}
}

// STATIC METHODS AND CONSTANTS
Expand All @@ -170,13 +170,13 @@ Promise.STATE_RUNNING = STATE_RUNNING;
Promise.STATE_RESOLVED = STATE_RESOLVED;
Promise.STATE_REJECTED = STATE_REJECTED;

Promise.exec = function (executor) {
return new Promise(executor).execute();
Promise.run = function (executor) {
return new Promise(executor).run();
};

Promise.all = function (promises) {

return Promise.exec(function (resolve, reject, notify) {
return Promise.run(function (resolve, reject, notify) {

// List of result values of each promises
// Values are in same order as promises list
Expand All @@ -201,7 +201,7 @@ Promise.all = function (promises) {

Promise.race = function (promises) {

return Promise.exec(function (resolve, reject, notify) {
return Promise.run(function (resolve, reject, notify) {
for (var i = 0; i < promises.length; i++)
// Pass notify callback to allow raced promised to notify
// Is it a good idea? I don't know but if you don't like it then don't use it!
Expand Down
2 changes: 1 addition & 1 deletion benchmark-next-tick/next-tick.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

global.nextTickPM = (function () {

var messageType = 'i20-promise-job';
var messageType = 'promise-job';
var pool = [];
var i = -1;

Expand Down
40 changes: 20 additions & 20 deletions tests/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ QUnit.module('Core behavior', function () {

var done = assert.async();

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 100, 'resolved');
}).then(function (value) {
assert.ok(true, 'Successfully resolved');
Expand All @@ -20,7 +20,7 @@ QUnit.module('Core behavior', function () {

var done = assert.async();

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
setTimeout(reject, 100, 'rejected');
}).then(function (value) {
assert.ok(false, 'Successfully rejected');
Expand All @@ -36,7 +36,7 @@ QUnit.module('Core behavior', function () {

var done = assert.async();

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
throw 'rejected';
}).then(function (value) {
assert.ok(false, 'Successfully rejected');
Expand All @@ -54,7 +54,7 @@ QUnit.module('Core behavior', function () {
var now = Date.now();
var delay = 100;

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, delay, 'resolved');
}).then(function (value) {
var then = Date.now();
Expand All @@ -71,7 +71,7 @@ QUnit.module('Core behavior', function () {

assert.expect(goal);

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
var interval = setInterval(function () {

i++;
Expand All @@ -96,7 +96,7 @@ QUnit.module('Chaining', function () {

var done = assert.async();

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 100, 'resolved');
}).then(function (value) {
return value.toUpperCase();
Expand All @@ -110,7 +110,7 @@ QUnit.module('Chaining', function () {

var done = assert.async();

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
setTimeout(reject, 100, 'rejected');
}).then(null, function (error) {
return error.toUpperCase();
Expand All @@ -124,7 +124,7 @@ QUnit.module('Chaining', function () {

var done = assert.async();

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 100, 'resolved');
}).then(function (value) {
throw value.toUpperCase();
Expand All @@ -138,7 +138,7 @@ QUnit.module('Chaining', function () {

var done = assert.async();

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
setTimeout(reject, 100, 'rejected');
}).then(null, function (error) {
throw error.toUpperCase();
Expand All @@ -152,10 +152,10 @@ QUnit.module('Chaining', function () {

var done = assert.async();

Promise.exec(function (resolve, reject, notify) {
Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 100, 'resolved');
}).then(function (value) {
return Promise.exec(function (resolve, reject, notify) {
return Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 100, value.toUpperCase());
});
}).then(function (value) {
Expand All @@ -173,11 +173,11 @@ QUnit.module('Combination', function () {

var done = assert.async();

var p1 = Promise.exec(function (resolve, reject, notify) {
var p1 = Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 200, 'resolved1');
});

var p2 = Promise.exec(function (resolve, reject, notify) {
var p2 = Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 100, 'resolved2');
});

Expand All @@ -195,11 +195,11 @@ QUnit.module('Combination', function () {

var done = assert.async();

var p1 = Promise.exec(function (resolve, reject, notify) {
var p1 = Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 200, 'resolved1');
});

var p2 = Promise.exec(function (resolve, reject, notify) {
var p2 = Promise.run(function (resolve, reject, notify) {
setTimeout(reject, 100, 'rejected2');
});

Expand All @@ -220,11 +220,11 @@ QUnit.module('Combination', function () {

var done = assert.async();

var p1 = Promise.exec(function (resolve, reject, notify) {
var p1 = Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 200, 'resolved1');
});

var p2 = Promise.exec(function (resolve, reject, notify) {
var p2 = Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 100, 'resolved2');
});

Expand All @@ -242,11 +242,11 @@ QUnit.module('Combination', function () {

var done = assert.async();

var p1 = Promise.exec(function (resolve, reject, notify) {
var p1 = Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 200, 'resolved1');
});

var p2 = Promise.exec(function (resolve, reject, notify) {
var p2 = Promise.run(function (resolve, reject, notify) {
setTimeout(reject, 100, 'rejected2');
});

Expand All @@ -267,7 +267,7 @@ QUnit.test('Execution flow', function (assert) {
var done = assert.async();
var i = 0;

var p1 = Promise.exec(function (resolve, reject, notify) {
var p1 = Promise.run(function (resolve, reject, notify) {
setTimeout(resolve, 100, i++);
});

Expand Down

0 comments on commit d632c95

Please sign in to comment.