Es6 Learning Path (ECMAScript 6 by Ruan Yifeng)

Since the knowledge was interspersed and there were many details in it, I felt a little inefficient when I read it in order for the first time, and I didn’t have the patience to finish reading a lot of content. The details will depend on Teacher Ruan Yifeng, this article is completely personal summary, omitted many definitions.

This time I’ll go straight to the one I don’t like: Promises

Promise has two features:

  • The status of an object is not affected.
  • Once the state changes, it never changes again, and you can get this result at any time.

Three disadvantages:

  • Unable to cancel the Promise.
  • If the callback function is not set, errors thrown internally by a Promise are not reflected externally.
  • When I’m in a pending state, I don’t know whether I’m just starting or ending.
const promise = new Promise(function(resolve, reject) { // ... Resolve (value); resolve(value); } else { reject(error); }});Copy the code

The Promise object is a constructor that generates instances. The Promise constructor takes a function as an argument. Resolve and Reject are two functions that take arguments to the Promise constructor’s arguments. Now we have our promise instance.

The resolve function changes the state of the Promise object from “unfinished” to “successful.” It will be called when the asynchronous operation succeeds and will pass the result of the asynchronous operation as an argument.

The Reject function changes the state of the Promise object from “unfinished” to “failed” (i.e., from Pending to Rejected). It is called when the asynchronous operation fails and passes the error reported by the asynchronous operation as a parameter.

I wonder what asynchronous operation succeeds and what asynchronous operation fails. And pass the result as a parameter. When I was practicing, I found that the instance of new would execute the constructor once and open the Little Red Book to check the process of new:

  • Create a new object
  • Assigns the scope of the constructor to the new object (hencethisIt points to this new object.)
  • Execute the code in the constructor (add attributes to this new object)
  • Return a new object
const promise = new Promise(function(resolve, reject) { console.log('Promise') let value = 10 error = 20 if (true){ resolve(value); } else { reject(error); }});Copy the code

Only one Promise will be printed. True means asynchronous success, so I made Promise asynchronous success, but actually I’ll leave it up to you to write that up. Resolve (value), so what is that? I don’t see anything. The result of an asynchronous operation is passed as a parameter, so this is a resoleve. Where do I receive it when it’s delivered?

The answer is to call the instance’s then() method:

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
Copy the code

In this case, the value of the first parameter is the value of resolve, and the error value is the value of reject. That is, the success and failure of asynchronous function calls are then operations. So when was catch used before?

Take a look at the example given by Teacher Ruan Yifeng:

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}

timeout(100).then((value) => {
  console.log(value);
});
Copy the code

The third and subsequent arguments to setTimeout are all other arguments passed to the execution function (IE9 and earlier versions do not support this argument). That is, resolve(‘done’) will be executed after ms and then will fetch the done. And so it is.

The tutorial points out that the callback specified by the then method will not be executed until all synchronization tasks in the current script have been executed.

let promise = new Promise(function(resolve, reject) { console.log('Promise'); resolve(); }); promise.then(function() { console.log('resolved.'); }); console.log('Hi! '); // Promise // Hi! // resolvedCopy the code

Although the Hi print was written before then, it was executed before the callback, indicating that it was executed after all synchronization tasks in the current script had been executed. Note the synchronization script.

  • Encapsulation ajax
  • Promise.prototype.then()

Prototype. Then () is a. Then null, rejection or. Then (). How do I remember catch and reject?

p.then((val) => console.log('fulfilled:', val)) .catch((err) => console.log('rejected', err)); => console.log(' pity :', val)). Then (null, (err) => console.log("rejected:", err)); // This is a big pity.Copy the code

Look at the code with Promise

// const promise = new promise (function(resolve, reject) {try {throw new Error('test'); } catch(e) { reject(e); }}); promise.catch(function(error) { console.log(error); }); // const promise = new promise (resolve, reject) {reject(new Error('test')); }); promise.catch(function(error) { console.log(error); });Copy the code

So there’s a try catch in the Promise that I haven’t used yet, and it says, let the code in the try fail, and if it does, execute the catch.

The try throws a reject(e) error, which is reject(e), and we can call the second argument to the then() callback, or we can call the.catch () callback. Teacher Ruan Yifeng suggested that we use catch to do reject.

Recommended writing:

promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });
Copy the code

Any errors in a Promise need to be passed through a catch

Const someAsyncThing = function() {return new Promise(resolve(x + 2)); }); }; someAsyncThing().then(function() { console.log('everything is great'); }); setTimeout(() => { console.log(123) }, 2000); // Uncaught (in promise) ReferenceError: x is not defined // 123Copy the code

In the code above, the Promise object generated by someAsyncThing() has a syntax error. When the browser runs this line, it will print ReferenceError: x is not defined, but it will not exit the process or terminate the script execution. After 2 seconds, it will still print 123. This means that errors within a Promise do not affect the code outside the Promise, which is colloquially known as “Promise eats errors.”

The catch() method still returns a Promise object, so you can call the then() method later.

const promise = new Promise(function(resolve, reject) {
  console.log('Promise')
  let value = 10
  let error = 20
    reject(error);
});
promise
.then( res => {
  console.log(res)
})
.catch(err => {
  xb
  console.log('catch1:',err)
})
.then(res => {
  console.log(res)
})
.catch(err =>{
  console.log('catch2:',err)
})
// Promise
// catch2: ReferenceError: xb is not defined
Copy the code

Here’s an example I wrote myself. First, the promise is reject, so catch is used to catch errors. Log (‘catch1:’,err) does not execute to console.log(‘catch1:’,err), stops when xB is encountered and jumps to the next catch. Obviously both procedures are reject, so THEN is never called once.

Promise. Prototype. Finally () this is very simple, is whether the resolve or reject will be called.

There are many more Promise apis in the future:

  • Promise.all
  • Promise.race
  • Promise.allSettled
  • Promise.any
  • Promise.resolve
  • Promise.reject

Promise. Resolve and Promise. Reject because these two apis are used in the previous ones.

Promise. Resolve will convert an existing object into a Promise object, teacher example

Resolve ('foo') // equivalent to new Promise(resolve => resolve('foo'))Copy the code

Four cases of parameters

  • Prmoise instance

Promise.resolve will return the instance intact without any modifications.

  • The parameter is one that can be usedthenMethod object

The promise.resolve () method converts this object to a Promise and immediately executes the thenable object’s then() method (which you must use, of course). . So then1 came first.

let thenable = { then: function(resolve, reject) { console.log('then1') resolve(42); }}; let p1 = Promise.resolve(thenable); //then1 p1.then(function (value) { console.log('then2') console.log(value); }); //then2 //42Copy the code
  • Parameters are not objects with then() methods, or are not objects at all

If the argument is a primitive value, or an object that does not have a then() method, the promise.resolve () method returns a new Promise object with a state of resolve.

const p = Promise.resolve('Hello');

p.then(function (s) {
  console.log(s)
});
// Hello
Copy the code

You get whatever you put in resolve and then.

  • It takes no parameters

The variable p is a Promise object

const p = Promise.resolve();

p.then(function () {
  // ...
});
---------------------------------------
setTimeout(function () {
  console.log('three');
}, 0);

Promise.resolve().then(function () {
  console.log('two');
});

console.log('one');

// one
// two
// three
Copy the code

Note that the Promise object for resolve() now is executed at the end of this event loop, not at the beginning of the next.

SetTimeout (fn, 0) is executed at the start of the next event loop, promise.resolve () is executed at the end of the current event loop, and console.log(‘one’) is executed immediately, so output first.

The promise.reject () method also returns a new Promise instance with a state of Rejected.

Const p = promise.reject (' error '); // const p = new Promise((resolve, reject) => reject(' error ')) p.hen (null, function (s) {console.log(s)}); / / make a mistakeCopy the code

If an instance is defined without a catch, an error is reported (a scarlet letter). Using catch is a console error.

With these two apis out of the way, let’s look at the other apis

  • Promise.all
  • Promise.race
  • Promise.allSettled
  • Promise.any

The promise.all () method is used to wrap multiple Promise instances into a new Promise instance.

const p = Promise.all([p1, p2, p3]);
Copy the code

In the code above, the promise.all () method takes an array of arguments. P1, P2, and p3 are all Promise instances. In addition, the promise.all () method can take arguments that are not arrays, but must have an Iterator interface and return each member as a Promise instance.

The state of P is determined by P1, P2 and P3, which can be divided into two cases.

(1) Only when the states of P1, P2 and P3 become depressing, the state of P will become depressing. At this time, the return values of P1, P2 and P3 will form an array and be passed to the callback function of P.

(2) As long as p1, P2 and P3 are rejected, P becomes rejected, and the return value of the first rejected instance is passed to p’s callback function.

Note that if a Promise instance that is a parameter defines its own catch method, it does not fire the promise.all () catch method once it is rejected. Because an instance of catch will then return a new Promise in the resolved state that can call then, all will not execute the catch.

The form of the promise.race () argument is the same, except that the logic is different. If one of the first instances of P1, P2, and P3 changes state, the state of P will change. The return value of the first changed Promise instance is passed to p’s callback. As with the promise.all () method, if it is not a Promise instance, the promise.resolve () method is called first, turning the parameter into a Promise instance, and then processing further. (Race: a race, so you can see why the race method is implemented logically.)

Promise. AllSettled () : The packaging instance will end only after all these parameter instances return the result, whether this is a pity or Rejected. This method was introduced by ES2020.

const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);

const allSettledPromise = Promise.allSettled([resolved, rejected]);

allSettledPromise.then(function (results) {
  console.log(results);
});
// [
//    { status: 'fulfilled', value: 42 },
//    { status: 'rejected', reason: -1 }
// ]
Copy the code

In the code above, the return value of promises.allsettled (), allSettledPromise, may become a pity. Its listener receives an array results as an argument. Each member of this array is an object corresponding to two Promise instances passed in promise.allSettled (). Each object has a status attribute, whose value can only be the string fulfilled or the string Rejected. Someday, the object has the value attribute, and the object has the reason attribute, which corresponds to the return values of the two states.

Promise.any():ES2021 introduces the promise.any () method. The method takes a set of Promise instances as parameters and returns them wrapped as a new Promise instance. As long as one parameter instance becomes a depressing state, the packaging instance will become a depressing state. If all parameter instances become the Rejected state, the wrapper instance becomes the Rejected state. Promise.any() is like the promise.race () method except that it does not end when a Promise changes to the Rejected state. Here’s an example:

var resolved = Promise.resolve(42);
var rejected = Promise.reject(-1);
var alsoRejected = Promise.reject(Infinity);

Promise.any([resolved, rejected, alsoRejected]).then(function (result) {
  console.log(result); // 42
});

Promise.any([rejected, alsoRejected]).catch(function (results) {
  console.log(results); // [-1, Infinity]
});
Copy the code

After reading this Promise, I found that I was not familiar with event loops, async, Interator and generator, so I decided to learn async in the next chapter