">
</div>
</div>
</figure></iframe></div></div></figure><p id="744a">Now you can see how resolve & reject<b> </b>method work. When promise is initiated, it accepts a callback function as a parameter. The callback function accepts 2 parameters: resolve method & reject method. The callback function is executed immediately when the promise is initiated(inside constructor method), and promise’s internal _resolve & _reject method is passed into the callback function. When the asynchronous operation is completed, _resolve & _reject is triggered to update the promise’s state and value.</p><p id="905a">You might be confused with line 37–39</p>
<figure id="9526">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/d2736cb40383c0d2e609e3846487af1e.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="4c11">They exist because resolve method could accept not only a string result, but also a promise. Take a look at below example:</p>
<figure id="abf1">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/554473f5ea5bfc1d965ecde8e1542e98.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="dcd5">When this code is executed, the following four promises are still created. Browser still registers the callback method of setTimeout (line 2 — line 8).</p><figure id="6207"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*6jGjGsWV-NOhx3ZsJPyt-Q.png"><figcaption></figcaption></figure><p id="4c1e">However, after 1 second, the callback method of setTimeout is executed, which creates a new promise — Promise 5. And a callback method to resolve promise 1 is added to promise 5’s handlers variable. Browser then registers the callback method of setTimeout(line 4– line 6)</p><figure id="f8cd"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*j4PbzBIIvcfhovp8DUixgw.png"><figcaption></figcaption></figure><p id="c327">In one second, promise 5 is resolved with value ‘some string’:</p><figure id="b898"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*Cvx__JIuRFwreqW7RG8lgA.png"><figcaption></figcaption></figure><p id="8174">Promise 5’s callback methods(inside handlers variable) are then executed, which resolves promise 1,</p><figure id="6ceb"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*sqmDbD-rS0cGbWTs10bIGQ.png"><figcaption></figcaption></figure><p id="2a57">Promise 1’s callback methods(inside handlers variable) are then executed, resolving promise 2, etc…</p><h1 id="80c9">Implement your own Promise.catch, finally method</h1><p id="0689">As the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">MDN</a> description pointed out, Promise.catch behaves the same as calling Promise.prototype.then(undefined, onRejected)</p><blockquote id="00d2"><p>The <code>catch()</code> method returns a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>Prom</code>ise</a> and deals with rejected cases only. It behaves the same as calling <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then"><code>Promise.prototype.then(undefined, onReject</code>ed)</a> (in fact, calling <code>obj.catch(onRejected)</code> internally calls <code>obj.then(undefined, onRejected)</code>). This means that you have to provide an <code>onRejected</code> function even if you want to fall back to an <code>undefined</code> result value - for example <code>obj.catch(() => {})</code>.</p></blockquote><p id="7ffc">Here is an implementation:</p>
<figure id="3a5a">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/a883060d2ce4818930a0df10ed7010b8.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="8d59"><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally">MDN</a> description for Promise.prototype.finally method</p><blockquote id="382b"><p>The <code><i>finally()</i></code> method returns a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"><co<i>de>Promise</co<i></a>. When the promise is finally either fulfilled or rejected, the specified callback function is executed. This provides a way for code to be run whether the promise was fulfilled successfully, or instead rejected.</p></blockquote><p id="d81c">One important callout is:</p><blockquote id="334d"><p>A <code>finally</code> callback will not receive any argument, since there's no reliable means of determining if the promise was fulfilled or rejected. This use case is for precisely when you <i>do not care</i> about the rejection reason, or the fulfillment value, and so there's no need to provide it. So for example:</p></blockquote><blockquote id="2870"><p>Unlike <code>Promise.resolve(2).then(() => {}, () => {})</code> (which will be resolved with <code>undefined</code>), <code>Promise.resolve(2).finally(() => {})</code> will be resolved with <code>2</code>.</p></blockquote><blockquote id="4bd5"><p>Similarly, unlike <code>Promise.reject(3).then(() => {}, () => {})</code> (which will be fulfilled with <code>undefined</code>), <code>Promise.reject(3).finally(() => {})</code> will be rejected with <code>3</code>.</p></blockquote><p id="d1d7">This makes our implementation a little different from just calling this.then(onFinally, onFinally).</p><p id="4109">Here is an implementation</p>
<figure id="cfa7">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/c7e25e30bab554ab9ab59cf774ebd32a.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="8f66">You can see the difference is that after executing onFinally method, we return a new Promise depends on the state and value of the promise before onFinally is executed.</p><h1 id="0923">Implement your own Promise.resolve & Promise.reject</h1><p id="d44f">You might be confused with the Promise.resolve method and Promise.reject method in the above example.</p><blockquote id="39b6"><p>When calling Promise.resolve(value), If the value is a promise, that promise is returned; if the value is a thenable (i.e. has a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then"><code>"then" met</code>hod</a>), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned promise will be fulfilled with the value. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve">MDN</a></p></blockquote>
<figure id="8da3">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/5299ebfa2bb45925156ca91f8283a6cc.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><blockquote id="83d5"><p>The <code>Promise.reject()</code> method returns a <code>Promise</code> object that is rejected with a given reason. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject">MDN</a></p></blockquote>
<figure id="ca09">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/857771d95169bfbeb7a415e569fc0198.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><h1 id="9902">Implement your own Promise.all & Promise.allSettled</h1><p id="4f31"><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all">MDN</a> for Promise.all method</p><blockquote id="7855"><p>The <code>Promise.all()</code> method takes an iterable of promises as an input, and returns a single <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>Prom</code>ise</a> that resolves to an array of the results of the input promises.</p></blockquote><blockquote id="dfdf"><p>This returned promise will resolve when all of the input's promises have resolved, or if the input iterable contains no promises.</p></blockquote>
Options
<blockquote id="6e1d"><p>It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.</p></blockquote><p id="3ced">Here is an implementation of the Promise.all method</p>
<figure id="331b">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/48cf66f04e56c93605a0a10739eb307d.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="f52c">The difference from Promise.all() and Promise.allSettled() is that Promise.all method returns a promise that rejects “eagerly”. However, Promise.allSettled() returns a promise that resolves/rejects when all promises are settled(fulfilled/rejected)</p><p id="e7b9"><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled">MDN</a> for Promise.allSettled()</p><blockquote id="c6b9"><p>The <code>Promise.allSettled()</code> method returns a promise that resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.</p></blockquote><p id="7af5">Below is an implementation:</p>
<figure id="68f1">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/72ccbe4e16381076745e504a08ef9535.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><h1 id="b2d5">Implement your own Promise.race & Promise.any</h1><p id="629b"><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race">MDN</a> for Promise.race()</p><blockquote id="4716"><p>The <code>Promise.race()</code> method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.</p></blockquote>
<figure id="49ef">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/2012e8929cafec8e8368a13ded51e2dc.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="5f56"><a href="http://Promise.any() takes an iterable of Promise objects. It returns a single promise that resolves as soon as any of the promises in the iterable fulfills, with the value of the fulfilled promise. If no promises in the iterable fulfill (if all of the given promises are rejected), then the returned promise is rejected with an AggregateError, a new subclass of Error that groups together individual errors.">MDN</a> for Promise.any()</p><blockquote id="6f9e"><p><code>Promise.any()</code> takes an iterable of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>Prom</code>ise</a> objects. It returns a single promise that resolves as soon as any of the promises in the iterable fulfills, with the value of the fulfilled promise. If no promises in the iterable fulfill (if all of the given promises are rejected), then the returned promise is rejected with an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError"><code>AggregateEr</code>ror</a>, a new subclass of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error"><code>Er</code>ror</a> that groups together individual errors.</p></blockquote><p id="8200">Promise.all return a new promise that will <b>resolve with the aggregated results from all promises</b> or reject with the error from the first rejected promise.</p><p id="c6bf">Promise.any instead returns a promise that resolves with the value from first resolved promise, or <b>rejects with the aggregated errors from all the rejected promises.</b></p>
<figure id="9961">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/bc2e40d442e4fb33da7cff975a0da2fe.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><h1 id="5f6f">Convert any callback to promise using Promisify helper method</h1><p id="0ff0">Sometimes, you may prefer promise syntax and want to convert your callback to a promise. Here is a helper method that achieves the functionality:</p>
<figure id="d630">
<div>
<div>
<iframe class="gist-iframe" src="/gist/FEE-P/6dbf40a233bab0ac7c9fb30f4897c8d5.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
</div>
</div>
</figure></iframe></div></div></figure><p id="0d30">That’s it for the implementation of Promise and related methods. Feel free to leave any comments or suggestions or give it a like if you enjoyed the article.</p>
<figure id="2aad">
<div>
<div>
<img class="ratio" src="http://placehold.it/16x9">
<iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FashtlvTyQhZFj7oUS6%2Ftwitter%2Fiframe&display_name=Giphy&url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FashtlvTyQhZFj7oUS6%2Fgiphy.gif&image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FashtlvTyQhZFj7oUS6%2Fgiphy.gif&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=giphy" allowfullscreen="" frameborder="0" height="186" width="435">
</div>
</div>
</figure></iframe></div></div></figure><h1 id="8e0d">Reference</h1><div id="c32f" class="link-block">
<a href="https://www.promisejs.org/implementing/">
<div>
<div>
<h2>Promises</h2>
<div><h3>by Forbes Lindesay This article was originally written as an answer on Stack Overflow. The hope is that by seeing how…</h3></div>
<div><p>www.promisejs.org</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/)"></div>
</div>
</div>
</a>
</div><div id="dac7" class="link-block">
<a href="https://promisesaplus.com/">
<div>
<div>
<h2>Promises/A+</h2>
<div><h3>A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is…</h3></div>
<div><p>promisesaplus.com</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/)"></div>
</div>
</div>
</a>
</div><div id="f7dd" class="link-block">
<a href="https://javascript.info/async">
<div>
<div>
<h2>Promises, async/await</h2>
<div><h3>Edit description</h3></div>
<div><p>javascript.info</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*H7g9YBZVnCIwYMLf)"></div>
</div>
</div>
</a>
</div><div id="5394" class="link-block">
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">
<div>
<div>
<h2>Promise - JavaScript | MDN</h2>
<div><h3>The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting…</h3></div>
<div><p>developer.mozilla.org</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*f2CEJ_jWLpyUnDT1)"></div>
</div>
</div>
</a>
</div><div id="b717" class="link-block">
<a href="https://readmedium.com/implement-a-simple-promise-in-javascript-20c9705f197a">
<div>
<div>
<h2>Implement a Simple Promise in Javascript</h2>
<div><h3>In front-end engineering interviews and daily front-end development, we encounter Promises all the time. In these…</h3></div>
<div><p>medium.com</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*B69CFWqVtDQTq-lq1TdauQ.jpeg)"></div>
</div>
</div>
</a>
</div></article></body>
How to implement your own Promise. Implement promise-related methods(race, any, all, allSettled, then, finally, catch, resolve & reject, promisify)
In this article, I’d like to walk you through a simplified implementation of ES6 Promise and its related methods.
Let’s look at an example of promise. In the following example, A promise is created and will resolve in1 second. A couple of methods are chained to transform the resolved result.
Could you try answer these questions:
What is a promise?
Where is resolve, reject coming from?
When calling resolve with ‘some string result’, what happens under the hood?
What is Promise chaining and why the syntax?
Sometimes I see Promise.resolve & Promise.reject, what do these methods do?
What are some best practices when writing promise or async /await?
etc…
Below is an example from AWS SDK. If you have used AWS JavaScript SDK before, you probably have seen something similar:
What in the world does promise() method do under the hood? How to reason about this code?
These questions all became clear to me after implementing my own simplified version of promise and promise-related methods from scratch. If you are having the similar questions with promise or async/await syntax like I did, I hope you will find this article helpful. If you have any suggestions or comments to this article, feel free to drop a message. All the references are attached in the end.
Before getting started, here are some pre-requisites that would help you understand why we want to use promise and how is asynchronous code executed in browser, these are the foundations to the final implementation, so don’t skip it.
After brushing up on the basics, let’s get started with implementing our own promise and promise-related methods.
Implement your own Promise & “then” method
The first place to check out what is a promise is probably the MDN description. (Don’t worry if it doesn’t make sense to you)
A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.
A Promise is in one of these states:
* pending: initial state, neither fulfilled nor rejected.
* fulfilled: meaning that the operation was completed successfully.
* rejected: meaning that the operation failed.
In the Promises/A+ spec, it is translated to something more reflective of the technical implementation:
A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled.
Below is how I picture a promise:
The promise is associated with the eventual result of an asynchronous operation.
At any time, the Promise is in one of the following state: pending, fulfilled or rejected. And once it is fulfilled or rejected, it will stay that way.
The then() method returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise. The interface of a then() method looks like this:
Below is an example to walk you through what happens when you create a promise and do promise chaining.
Promise 1 is created when executing line 1 — line 5. Promise 1 is set at pending state when created. The asynchronous operation hasn’t finished yet and will be finished in 1 second to resolve promise 1.
State at line 5
line 8–10 is then executed, the first callback function is added to the handlers variable of promise 1, and a new promise — Promise 2 is returned at line 10.
The then method at line 10 adds a callback to Promise 2’s handlers variable, and returns a new promise — Promise 3
The catch method at line 13 adds a handler to the promise 3 and returns a new promise — promise 4
After 1 second, line 3 is executed, promise 1 is resolved. When resolving promise 1, its state is updated to ‘fulfilled’ with value: ‘some string result’.
All promise 1’s callback methods(inside handlers variable) are then executed, after all the callback methods are executed, promise 2 is fulfilled.
All promise 2’s callback methods(inside handlers variable) are then executed, after all the callback methods are executed, promise 3 is fulfilled.
All promise 3’s callback methods(inside handlers variable) are then executed, after that, promise 4 is fulfilled.
Now let’s look at the implementation.
Now you can see how resolve & rejectmethod work. When promise is initiated, it accepts a callback function as a parameter. The callback function accepts 2 parameters: resolve method & reject method. The callback function is executed immediately when the promise is initiated(inside constructor method), and promise’s internal _resolve & _reject method is passed into the callback function. When the asynchronous operation is completed, _resolve & _reject is triggered to update the promise’s state and value.
You might be confused with line 37–39
They exist because resolve method could accept not only a string result, but also a promise. Take a look at below example:
When this code is executed, the following four promises are still created. Browser still registers the callback method of setTimeout (line 2 — line 8).
However, after 1 second, the callback method of setTimeout is executed, which creates a new promise — Promise 5. And a callback method to resolve promise 1 is added to promise 5’s handlers variable. Browser then registers the callback method of setTimeout(line 4– line 6)
In one second, promise 5 is resolved with value ‘some string’:
Promise 5’s callback methods(inside handlers variable) are then executed, which resolves promise 1,
Promise 1’s callback methods(inside handlers variable) are then executed, resolving promise 2, etc…
Implement your own Promise.catch, finally method
As the MDN description pointed out, Promise.catch behaves the same as calling Promise.prototype.then(undefined, onRejected)
The catch() method returns a Promise and deals with rejected cases only. It behaves the same as calling Promise.prototype.then(undefined, onRejected) (in fact, calling obj.catch(onRejected) internally calls obj.then(undefined, onRejected)). This means that you have to provide an onRejected function even if you want to fall back to an undefined result value - for example obj.catch(() => {}).
Here is an implementation:
MDN description for Promise.prototype.finally method
The finally() method returns a de>Promise. When the promise is finally either fulfilled or rejected, the specified callback function is executed. This provides a way for code to be run whether the promise was fulfilled successfully, or instead rejected.
One important callout is:
A finally callback will not receive any argument, since there's no reliable means of determining if the promise was fulfilled or rejected. This use case is for precisely when you do not care about the rejection reason, or the fulfillment value, and so there's no need to provide it. So for example:
Unlike Promise.resolve(2).then(() => {}, () => {}) (which will be resolved with undefined), Promise.resolve(2).finally(() => {}) will be resolved with 2.
Similarly, unlike Promise.reject(3).then(() => {}, () => {}) (which will be fulfilled with undefined), Promise.reject(3).finally(() => {}) will be rejected with 3.
This makes our implementation a little different from just calling this.then(onFinally, onFinally).
Here is an implementation
You can see the difference is that after executing onFinally method, we return a new Promise depends on the state and value of the promise before onFinally is executed.
Implement your own Promise.resolve & Promise.reject
You might be confused with the Promise.resolve method and Promise.reject method in the above example.
When calling Promise.resolve(value), If the value is a promise, that promise is returned; if the value is a thenable (i.e. has a "then" method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned promise will be fulfilled with the value. MDN
The Promise.reject() method returns a Promise object that is rejected with a given reason. MDN
Implement your own Promise.all & Promise.allSettled
The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises.
This returned promise will resolve when all of the input's promises have resolved, or if the input iterable contains no promises.
It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.
Here is an implementation of the Promise.all method
The difference from Promise.all() and Promise.allSettled() is that Promise.all method returns a promise that rejects “eagerly”. However, Promise.allSettled() returns a promise that resolves/rejects when all promises are settled(fulfilled/rejected)
The Promise.allSettled() method returns a promise that resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.
The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.
Promise.any() takes an iterable of Promise objects. It returns a single promise that resolves as soon as any of the promises in the iterable fulfills, with the value of the fulfilled promise. If no promises in the iterable fulfill (if all of the given promises are rejected), then the returned promise is rejected with an AggregateError, a new subclass of Error that groups together individual errors.
Promise.all return a new promise that will resolve with the aggregated results from all promises or reject with the error from the first rejected promise.
Promise.any instead returns a promise that resolves with the value from first resolved promise, or rejects with the aggregated errors from all the rejected promises.
Convert any callback to promise using Promisify helper method
Sometimes, you may prefer promise syntax and want to convert your callback to a promise. Here is a helper method that achieves the functionality:
That’s it for the implementation of Promise and related methods. Feel free to leave any comments or suggestions or give it a like if you enjoyed the article.