This is the 8th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

preface

Promaise is all too familiar, Promise is a solution to asynchronous programming that is more rational and powerful than traditional solutions, callbacks and events. A Promise, simply put, is a container that holds the result of an event (usually an asynchronous operation) that will end in the future.

The Promise API for ES6 doesn’t provide many methods, but some useful ones can be deployed on their own. Here’s how to deploy two useful methods that are not in ES6. The done method and finally method. In the first place, finally method is used more often than done method. In the second place, done method is used less often than done method.

  1. How does the done method work? Can you implement one yourself?
  2. The finally methodOperation mechanism.Writing aLook at it?
  3. Done, finallyThe last execution?

This could be an essay question, or it could be an answer question.

These questions are often asked now, because promiser’s other related questions have been familiar to us. Today I’ll take a look at these unfamiliar questions.

1. done

If you’ve ever used the Promise library, you’ve probably seen the done method. The Promise library mentions promise.prototype. done, and uses the done method instead of the THEN method. There is no specification for promise.prototype. done in the Promise specification and the Promise+ specification. It all starts with those “vanishing mistakes.”

Vanishing error

Let’s recall what promises are all about. “The state of the object is not affected by the outside world.” “Once the state changes, it will not change again. This result can be obtained at any time.” Also recall the drawbacks of promises: “You can’t cancel a Promise, it executes as soon as it’s created, you can’t cancel in mid-stream”, “When in the Pending state, you can’t tell what stage you are in (just started or about to finish)”, “If you don’t set the callback function, Errors thrown internally by the Promise are not reflected externally.

As you can probably see from the last flaw, whether a Promise ends in a THEN or a catch method, if the last method throws an error, it may not be caught (because errors within a Promise do not bubble globally). Let’s look at an example:

function JSONPromise(value) {
    return new Promise(function (resolve) {
        resolve(JSON.parse(value));
    });
}
// Run the sample
const string = "An invalid JSON string";
JSONPromise(string).then(function (object) {
    console.log(object);
}).catch(function(error){
    // => When json. parse throws an exception
    console.error(error);
});
Copy the code

Since string is an invalid JSON string, an error is thrown by parsing and then caught. Normally you write a catch, but if you don’t write it or miss it, once an exception occurs, finding the source is a very tricky problem.

function JSONPromise(value) {
    return new Promise(function (resolve) {
        resolve(JSON.parse(value));
    });
}
// Run the sample
const string = "An invalid JSON string";
JSONPromise(string).then(function (object) {
    console.log(object);
});
Copy the code

While this example may be simple, the use of promises in actual development is certainly much more complex, and exceptions to the code can vary. However, due to the Promise’s try-catch mechanism, this problem can be digested within the Promise, known as a vanishing error. Of course, some of you will say that if I catch every time I call it, it is definitely the best thing. But not everyone is as excellent as you 😁. If an error in this example occurs during implementation, it will be difficult to troubleshoot the error.

The error is unhandled rejection of the machine. There is a handle for unhandled Rejection in many Promise libraries. Such as:

  • When yPromise detects an UnHANDLED Rejection error, it prompts a corresponding message on the console. 【Promise rejected but no error handlers were registered to it】
  • In the case of obvious human errors, such as referenceErrors, Bluebird displays them directly to the console. [Possibly unhandled referenceerror.xxx]
  • Native Promise implementations address the same problem by providing gC-based Unhandled Rejection Tracking. This function is a mechanism for error display if an Unhandled Rejection is made for a Promise object when it is collected by the garbage collector. Both Firefox and Chrome native Promises are partially implemented.

Principle of implementation

Its implementation code is fairly simple.

Promise.prototype.done = function (onFulfilled, onRejected) {
  this.then(onFulfilled, onRejected)
    .catch(function (reason) {
      // Throw a global error
      setTimeout(() = > { throw reason }, 0);
    });
};
Copy the code

As you can see from the code above, the done method can be used just like the THEN method, providing callbacks for the Fulfilled and Rejected states, or it can be used without any arguments. But either way, DONE catches any possible errors and throws them globally. If you want to be strict, you can also write:

"use strict";
if (typeof Promise.prototype.done === "undefined") {
    Promise.prototype.done = function (onFulfilled, onRejected) {
        this.then(onFulfilled, onRejected).catch(function (error) {
            setTimeout(function () {
                throw error;
            }, 0);
        });
    };
}
Copy the code

summary

Done does not return a Promise object, so no catch can be used after done. Done errors are thrown directly, and Promise errors are not handled. Promises have powerful error handling, while done skips error handling in functions and throws exceptions directly.

Now that you’ve seen the done method why there is done, let’s look at finally methods if you implement one yourself.

2. finally

The finally method is used to specify the action that will be performed regardless of the final state of the Promise object. Its biggest difference from the done method is that it takes a normal callback function as an argument, which must be executed anyway.

server.listen(0)
  .then(function () {
    // run test
  })
  .finally(server.stop);
Copy the code

Why not .then(f, f)?

Finally (func) is essentially similar to then (func, func), but different in some key ways:

  • When you create a function inline, you can pass it once instead of having to declare it twice or create a variable for it

  • Because there is no reliable way to determine whether a Promise has been fulfilled, the finally callback will receive no parameters. It is this use case that applies to situations where you do not care about the reason for the rejection or the value of the realization and therefore do not need to provide it.

  • And Promise. Resolve (2). Then (() = > {}, () = > {}) (will use undefined analysis), Promise. Resolve (2). The finally (() = > {}) will be in 2. To solve

  • Also, and Promise. Reject (3). Then (() = > {}, () = > {}) (will use undefined analysis), Promise. Reject (3) finally (() = > {}) will be rejected. 3.

Principle of implementation

It is also simple to implement.

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value= > P.resolve(callback()).then(() = > value),
    reason= > P.resolve(callback()).then(() = > { throw reason })
  );
};
Copy the code

This will be fulfilled fulfilled or rejected. This function will be fulfilled.

summary

The finally method is essentially a THEN method, so in order to call the THEN method in an implementation method, the argument to the THEN method is a function that needs to be executed in the THEN method

Use promise. resolve to wait for the incoming function to finish executing, and return the previous THEN value. The reject method needs to throw an error message.

Who does the last thing?

Before we discuss this problem, we Promise. The first prototype. What finally converted to ES5.

"use strict";

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(value= > P.resolve(callback()).then(() = > value), reason= > P.resolve(callback()).then(() = > {
    throw reason;
  }));
};
Copy the code

Online conversion: es6console.com/, babeljs. IO /repl

“Finally” is not necessarily the last link in the promise chain. In fact, “done” is. Because finally may be followed by then, catch, and so on, it must return a promise object. Is not instant seconds to understand.

conclusion

Today, I introduced the done method and finally method of Promise, and also hand-written their implementation from the perspective of principle. These two methods can also be used in projects, but note the compatibility, not all places can use. I hope you found today’s article helpful.

If you think it’s good, give it a like.

reference

  • jsrun.net/t/jZKKp
  • Blog.csdn.net/momDIY/arti…
  • zhuanlan.zhihu.com/p/61681036
  • www.kancloud.cn/freya001/in…
  • www.kancloud.cn/kancloud/pr…