Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement Promise prototype method

2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces you how to implement the Promise prototype method, the content is very detailed, interested friends can refer to, hope to be helpful to you.

Promise is a solution to asynchronous programming, which was first proposed and implemented by the community. ES6 wrote it into the language standard, unified usage, and natively provided Promise objects.

I. [preface]

In the previous section, you implemented a chained call to Promise. Chain call is not only the difficulty but also the key point of Promise. So far, the implementation of Promise is as follows:

Class Promise {callbacks = []; state = 'pending';// added state value = null;// save result constructor (fn) {fn (this._resolve.bind (this));} then (onFulfilled) {return new Promise (resolve = > {this._handle ({onFulfilled: onFulfilled | | null, resolve: resolve})) });} _ handle (callback) {if (this.state = 'pending') {this.callbacks.push (callback); return;} / / if nothing is passed in the then if (! callback.onFulfilled) {callback.resolve (this.value); return } var ret = callback.onFulfilled (this.value); callback.resolve (ret);} _ resolve (value) {if (value & & (typeof value = 'object' | | typeof value = =' function')) {var then = value.then; if (typeof then = = 'function') {then.call (value, this._resolve.bind (this)) Return;}} this.state = 'fulfilled';// change state this.value = value;// save result this.callbacks.forEach (callback = > this._handle (callback));}}

This section focuses on the implementation of the Promise prototype method, including the implementation of catch, finally, and rejected state.

2. [error handling]

Previously, in order to explain the principle, only implemented onFulfilled, for Promise, in addition to success and failure, in the event of failure, to mark the status of Promise as rejected, and execute the registered onRejected. As shown in the following Demo:

/ * simulate an abnormal asynchronous request * @ param {*} url * @ param {*} s * @ param {*} callback * / const mockAjax = (url, s, callback) = > {setTimeout () = > {callback (url + 'asynchronous request takes' + s + 'seconds', 'error!') }, 1000 * s)} / / demo rejectnew Promise ((resolve, reject) = > {mockAjax ('getUserId', 1, function (result, error) {if (error) {reject (error)} else {resolve (result);}})} .then (result = > {console.log (result);}, error = > {console.log (error);})

With previous experience with fulfilled state, it is easy to support error handling by adding new reject logic to register callbacks and handle state changes.

/ / complete implementation + rejectclass Promise {callbacks = []; state = 'pending';// added state value = null;// save result constructor (fn) {fn (this._resolve.bind (this), this._reject.bind (this) } then (onFulfilled, onRejected) {return new Promise ((resolve, reject) = > {this._handle ({onFulfilled: onFulfilled | | null, onRejected: onRejected | | null, resolve: resolve, reject: reject});}) } _ handle (callback) {if (this.state = 'pending') {this.callbacks.push (callback); return;} let cb = this.state =' fulfilled'? Callback.onFulfilled: callback.onRejected; if (! cb) {/ / if nothing is passed in then cb = this.state = = 'fulfilled'? Callback.resolve: callback.reject; cb (this.value); return;} let ret = cb (this.value); cb = this.state = = 'fulfilled'? Callback.resolve: callback.reject; cb (ret);} _ resolve (value) {if (value & & (typeof value = 'object' | | typeof value = =' function')) {var then = value.then; if (typeof then = 'function') {then.call (value, this._resolve.bind (this), this._reject.bind (this)); return }} this.state = 'fulfilled';// change state this.value = value;// save result this.callbacks.forEach (callback = > this._handle (callback));} _ reject (error) {this.state =' rejected'; this.value = error; this.callbacks.forEach (callback = > this._handle (callback));}}

Source code of demo-reject

The running results are as follows:

[Promse-1]: constructor [Promse-1]: Ten [Promse-2]: constructor [promse-1]: _ handle state= signing [promse-1]: _ handle callbacks= [{onFulfilled: [Function], onRejected: [Function], resolve: [Function], reject: [Function]}] = > Promise {callbacks: [], name: 'Promse-2', state:' pending' Value: null} [Promse-1]: _ project [Promse-1]: _ reject value= error! [Promse-1]: _ handle state= rejected error! [Promse-2]: _ project [Promse-2]: _ reject value= undefined III, [exception handling]

I just introduced error handling, which refers to errors found in the constructor of Promise and notified through reject. What if an exception occurs while executing onFulfilled or onRejected? For such exceptions, handling is also simple, you can use try-catch to catch errors, and then set the corresponding Promise state to rejected state. The method of transforming _ handle is as follows:

_ handle (callback) {if (this.state = 'pending') {this.callbacks.push (callback); return;} let cb = this.state =' fulfilled'? Callback.onFulfilled: callback.onRejected; if (! cb) {/ / if nothing is passed in then cb = this.state = = 'fulfilled'? Callback.resolve: callback.reject; cb (this.value); return;} let ret; try {ret = cb (this.value); cb = this.state = = 'fulfilled'? Callback.resolve: callback.reject;} catch (error) {ret = error; cb = callback.reject} finally {cb (ret);}}

Source code of demo-error

No matter whether it is an error or an exception, it is finally implemented through reject, so it can be seen that the final handling of errors and exceptions can be handled through onRejected in then. So add a separate catch method, which is an alias for .then (null, onRejected). As follows:

Then (onFulfilled, onRejected) {return new Promise ((resolve, reject) = > {this._handle ({onFulfilled: onFulfilled | | null, onRejected: onRejected | | null, resolve: resolve, reject: reject});} catch (onError) {return this.then (null, onError);}

Source code of demo-catch

4. [Finally method]

In practical application, it is easy to encounter scenarios where some onDone is performed regardless of the final state of the Promise. For example, the server uses Promise to process the request, and then uses the finally method to shut down the server:

Server.listen (port) .then (function () {/ / do something}) .catch (error= > {/ / handle error}) .finally (server.stop)

In essence, because it is a variant of then. The effect of demo above is equivalent to the following code:

Server.listen (port) .then (function () {/ / do something}) .catch (error= > {/ / handle error}) .then (server.stop, server.stop)

From the above analysis, it seems that finally can be achieved as follows:

Finally (onDone) {return this.then (onDone, onDone);}

However, since the onDone of the finally method does not care whether the state of the Promise is fulfilled or rejected, the operation in the onDone should be state-independent and should not have any parameters.

If you use then to implement it, it does not conform to the description of "Why not. Then (f, f)?" in the Promise specification. On the one hand, onDone has parameters, and on the other hand, when onDone returns a Promise, it will change the state of the Promise returned by finally.

According to the specification, the finally implementation is as follows:

Catch (onError) {return this.then (null, onError);} finally (onDone) {if (typeof onDone! = = 'function') return this.then (); let Promise = this.constructor; return this.then (value = > Promise.resolve (onDone ()). Then (() = > value), reason = > Promise.resolve (onDone ()). Then (() = > {throw reason}));}

Source code of demo-finally

New Promise ((resolve, reject) = > {setTimeout () = > {resolve ('success');}, 1000)}) .finally (() = > {console.log (' onDone')})

For the above example, the execution result is as follows:

[Promse-1]: constructor [promse-1]: Ten [promse-2]: constructor [promse-1]: _ handle state= signing [promse-1]: _ handle callbacks= [{onFulfilled: [Function], onRejected: [Function], resolve: [Function], reject: [Function]}] = > Promise {callbacks: [], name: 'Promse-2', state:' pending' Value: null} [Promse-1]: _ resolve value= employees [promse-1]: _ handle state= fulfilledonDonePromise:: employees [Promse-3]: constructors [promse-3]: _ handle state= fulfilledonDonePromise:: [promse-3]: _ resolve value= undefine d [promse-3]: then[ promse-4]: constructor [promse-3]: _ handle state= fulfillment [promse-4]: _ constructor [promse-2]: _ resolve value= Promise {promse: [] Name: 'Promse-4', state:' fulfilled', value: 'success'} [Promse-4]: the [Promse-5]: constructor [promse-4]: _ handle state= fulfilled [promse-2]: _ resolve value= [promse-2]: _ resolve value= [promse-5]: _ Promse-5]: _ resolve value= undefined

You can also restore this process by cosmetic animation:

(Promise.finally demo animation) Click Open > >

The implementation of finally looks simple, but it is difficult to understand actually. For the above example, there are actually five Promise instances generated in the middle. As shown in the following figure:

On how to implement the Promise prototype method to share here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report