Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improves implementing page readability #37

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 118 additions & 38 deletions views/implementing.jade
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@ block content
done = true
onRejected(reason)
})
} catch (ex) {
} catch (e) {
if (done) return
done = true
onRejected(ex)
onRejected(e)
}
}

Expand Down Expand Up @@ -231,6 +231,92 @@ block content
li it is never called until the next tick (i.e. after the #[code .done] method has returned)
li it is called regardless of whether the promise is resolved before or after we call #[code .done]

:js
// manages handlers according to Promise state
function handle(handler) {
if (state === PENDING) {
handlers.push(handler);
} else {
if (state === FULFILLED &&
typeof handler.onFulfilled === 'function') {
handler.onFulfilled(value);
}
if (state === REJECTED &&
typeof handler.onRejected === 'function') {
handler.onRejected(value);
}
}
}

this.done = function (onFulfilled, onRejected) {
// ensure we are always asynchronous
setTimeout(function () {
handle({
onFulfilled: onFulfilled,
onRejected: onRejected
});
}, 0);
}

p.
We make sure to notify the handlers when the Promise is resolved or rejected.
We only ever do this in the next tick by removes them from the queue.

:js
function fulfill(result) {
state = FULFILLED;
value = result;

// runs handlers and resets queue
handlers.forEach(handle);
handlers = [];
}

function reject(error) {
state = REJECTED;
value = error;

// runs handlers and resets queue
handlers.forEach(handle);
handlers = [];
}

h2#then Observing (via .then)

p.
Now that we have #[code .done] implemented, we can easily implement #[code .then] to
just do the same thing, but construct a new Promise in the process.

:js
this.then = function (onFulfilled, onRejected) {
var self = this;
return new Promise(function (resolve, reject) {
return self.done(function (result) {
if (typeof onFulfilled === 'function') {
try {
return resolve(onFulfilled(result));
} catch (e) {
return reject(e);
}
} else {
return resolve(result);
}
}, function (error) {
if (typeof onRejected === 'function') {
try {
return resolve(onRejected(error));
} catch (e) {
return reject(e);
}
} else {
return reject(error);
}
});
});
}

h2#allcode The whole implementation

:js
var PENDING = 0;
var FULFILLED = 1;
Expand All @@ -249,13 +335,17 @@ block content
function fulfill(result) {
state = FULFILLED;
value = result;

// runs handlers and resets queue
handlers.forEach(handle);
handlers = null;
}

function reject(error) {
state = REJECTED;
value = error;

// runs handlers and resets queue
handlers.forEach(handle);
handlers = null;
}
Expand All @@ -273,6 +363,7 @@ block content
}
}

// manages handlers according to Promise state
function handle(handler) {
if (state === PENDING) {
handlers.push(handler);
Expand All @@ -298,45 +389,34 @@ block content
}, 0);
}

doResolve(fn, resolve, reject);
}

p.
We make sure to notify the handlers when the Promise is resolved or rejected.
We only ever do this in the next tick.

h2#then Observing (via .then)

p.
Now that we have #[code .done] implemented, we can easily implement #[code .then] to
just do the same thing, but construct a new Promise in the process.

:js
this.then = function (onFulfilled, onRejected) {
var self = this;
return new Promise(function (resolve, reject) {
return self.done(function (result) {
if (typeof onFulfilled === 'function') {
try {
return resolve(onFulfilled(result));
} catch (ex) {
return reject(ex);
this.then = function (onFulfilled, onRejected) {
var self = this;
return new Promise(function (resolve, reject) {
return self.done(function (result) {
if (typeof onFulfilled === 'function') {
try {
return resolve(onFulfilled(result));
} catch (e) {
return reject(e);
}
} else {
return resolve(result);
}
} else {
return resolve(result);
}
}, function (error) {
if (typeof onRejected === 'function') {
try {
return resolve(onRejected(error));
} catch (ex) {
return reject(ex);
}, function (error) {
if (typeof onRejected === 'function') {
try {
return resolve(onRejected(error));
} catch (e) {
return reject(e);
}
} else {
return reject(error);
}
} else {
return reject(error);
}
});
});
});
}

doResolve(fn, resolve, reject);
}

h2#apendix Further Reading
Expand Down