Last active
August 22, 2017 04:02
-
-
Save hoodwink73/1475d907f83cf4f9b5281c7e537155ca to your computer and use it in GitHub Desktop.
Promises are the power horse of async paradigm in JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// try-catch blocks cannot handle async errors | |
function foo() { | |
setTimeout( function(){ | |
baz.bar(); | |
}, 100 ); | |
} | |
try { | |
foo(); | |
// later throws global error from `baz.bar()` | |
} | |
catch (err) { | |
// never gets here | |
} | |
// to get around these, we started using | |
// error-first callback pattern | |
function foo(cb) { | |
setTimeout( function(){ | |
try { | |
var result = baz.bar() | |
cb(null, result) | |
} catch (e) { | |
cb(e) | |
} | |
}, 100 ); | |
} | |
// this works, but what if `baz.bar` has an async block inside which | |
// throws an error after an arbitary amount of time, it will suffer from | |
// the same shortcoming – try-catch blocks cannot catch async errors | |
// so, error-first callbacks are not composable, unless we keep on passing | |
// callbacks upwards to catch errors |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var p = Promise.resolve(21); | |
// `then` is the magic sauce which transforms a promise | |
// what computation results in the transformation, you ask? | |
// the logic inside the fulfillment callback | |
var p2 = p.then(function fulfillmentCallback (v) { | |
console.log(v); // 21 | |
return v * 2; | |
}) | |
// `p2` is a new promise which gets resolved | |
// with value `v * 2` since it was returned by | |
// the `fulfillmentCallback` | |
p2.then(function (v) { | |
console.log(v); // 42 | |
}) | |
// But `then`s are chainable, we could do without | |
// saving the intermediate promise in `p2` | |
p | |
.then(v => v * 2) | |
.then(v => log(v)) // 42 | |
// Above, we are creating sequence of steps following | |
// a presumably async action | |
// each call to `then` are just a step in this sequence | |
// But what if we wanted each step to have the affordance | |
// to be performed asynchronously | |
// we can return a Promise from the `fulfillmentCallback` passed | |
// to `then` | |
p | |
.then(v => | |
new Promise( | |
(resolve, reject) => | |
resolve(v * 2) | |
) | |
) | |
// this step will be passed the value | |
// with the above Promise resolves | |
// note intuition might suggest that | |
// the `fulfillmentCallback` in this step | |
// would get passed the Promise as an argument | |
// but thats not what it would get | |
.then(v => log(v)) // 42 | |
// now a promise can resolve right away | |
// or later, so any step now in the sequence | |
// can be delayed until the resolution of the previous step | |
p | |
.then(v => | |
new Promise( | |
(resolve, reject) => | |
setTimeout(() => resolve(v * 2), 1000) | |
) | |
) | |
.then(v => log(v)) // 42 | |
// above we see examples of how messages are passed | |
// through each step in the aync sequence. But it is not | |
// necessary that each needs to pass a message, a step's resolution | |
// can solely serve as a signal for the next step in the sequence to begin | |
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) | |
delay(100) | |
.then( | |
// note that there is no message being passed from | |
// the previous step | |
() => | |
return delay(200) | |
) | |
.then(() => console.log('I will happen after 300ms')) | |
// when a promise fails, but there is no rejection handler, | |
// the promise chain makes an assumption | |
p = new Promise(function (resolve, reject) { | |
reject(42); | |
}) | |
// here `p` is rejected, but because it is not | |
// handled, `p2` will also get rejected with the | |
// same error, this is how an error propagates a | |
// promise chain | |
p2 = p.then(function () { | |
// never gets here | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (!Promise.map) { | |
Promise.map = function (vals, cb) { | |
return Promise.all(vals.map(function () { | |
return new Promise(function (resolve) { | |
cb(val, resolve) | |
}) | |
})) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
d |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment