当前位置:网站首页>Jsliang job series - 07 - promise

Jsliang job series - 07 - promise

2020-11-08 16:10:00 jsliang

One Catalog

No frills front end , What's the difference with salted fish

Catalog
One Catalog
Two Preface
2.1 Thinking about it
2.2 reference
3、 ... and Promise On
3.1 What is it?
3.2 Why?
3.3 How to use it?
Four Promise Basics
4.1 new Promise
4.2 Promise state
5、 ... and Question bank : Basic questions
5.1 Topic 1
5.2 Topic two
5.3 Topic three
5.4 Topic four
5.5 Topic 5
5.6 Topic 6
6、 ... and Question bank : combination setTimeout
6.1 Topic 1
6.2 Topic two
6.3 Topic three
6.4 Topic four
6.5 Topic 5
6.6 Topic 6
6.7 Topic 7
7、 ... and .then() Chain operation
7.1 Two parameters
7.2 call chaining
8、 ... and .catch() Capture problem
Nine .finally() Enforcement
Ten Question bank :.then()、.catch()、.finally()
10.1 Topic 1
10.2 Topic two
10.3 Topic three
10.4 Topic four
10.5 Topic 5
10.6 Topic 6
10.7 Topic 7
10.8 Topic 8
10.9 Topic nine
10.10 Topic ten
10.11 Topic eleven
10.12 Topic twelve
10.13 Topic thirteen
10.14 Topic fourteen
11、 ... and .all() Relay race
Twelve .race() Individual competition
13、 ... and Question bank :.all()、.race()
13.1 Topic 1
13.2 Topic two
13.3 Topic three
13.4 Topic four
fourteen Promise Source code
15、 ... and Question bank : combination async/await
15.1 Topic 1
15.2 Topic two
15.3 Topic three
15.4 Topic four
15.5 Topic 5
15.6 Topic 6
15.7 Topic 7
15.8 Topic 8
15.9 Topic nine
15.10 Topic ten
15.11 Topic eleven
sixteen Comprehensive questions
16.1 Topic 1
16.2 Topic two
16.3 Topic three
seventeen Big factory
17.1 Use Promise Output every second 1、2、3
17.2 Use Promise The traffic lights turn on repeatedly
17.3 Realization mergePromise function
17.4 according to PromiseA+ Realize one of your own Promise
17.5 Encapsulate a method to load images asynchronously
17.6 Limit the number of concurrent asynchronous operations and complete them as quickly as possible
17.7 JS Implement asynchronous scheduler
eighteen summary

[](url)

Two Preface

Return directory

This article will combine Promise Knowledge point + Training questions in the form of explanation .

Pre knowledge points :

If you don't know these knowledge points well , Please click to view , Avoid being possessed by the devil .

2.1 Thinking about it

Return directory

JavaScript The evolution of asynchronous solutions in , It's in the following order :

  • callback -> promise -> generator -> async/await

In the computer industry , There is a myth of simple reductionism :

  • The closer you get to the bottom , The higher the technical content .
  • Every programmer has the pursuit of understanding the underlying source code .

This is true to a certain extent .

however , We should see that too , Once between the bottom and the surface , There's a domain gap . Master the bottom , It doesn't mean at the surface level .

For example, game developers , Not necessarily the best in the game . This is in FPS Especially in shooting or fighting games , Most of the top players in these games , I can't write code at all .

If you will be proficient in Promise Defined as , Good at using in various asynchronous scenarios Promise solve the problem .

that , Be able to write Promise Realization , Proficient in Promise It doesn't help much .

It comes from the official account of WeChat : Industrial Agglomeration

2.2 reference

Return directory

Please understand that this is a job 2 More than years of small front-end finishing , May ignore some of the essence of big guy articles. , In order to make an inappropriate order .

The following articles do not rank in any order , It's just personal comparison , There is not a trace of denigration , All the articles are read with worship .

good

Handwriting Promise

Promises/A+ standard

Add experience to

3、 ... and Promise On

Return directory

3.1 What is it?

Return directory

What is? Promise

Let's just print it out :

console.dir(Promise);
/*
Promise(
  all: ƒ all()
  arguments: (...)
  caller: (...)
  length: 1
  name: "Promise"
  prototype: Promise {constructor: ƒ, then: ƒ, catch: ƒ, finally: ƒ, Symbol(Symbol.toStringTag): "Promise"}
  race: ƒ race()
  reject: ƒ reject()
  resolve: ƒ resolve()
  Symbol(Symbol.species): (...)
  Symbol(allSettled): ƒ (d)
  get Symbol(Symbol.species): ƒ [Symbol.species]()
  __proto__: ƒ ()
  [[Scopes]]: Scopes[0]
)
*/

Yes ,Promise It's a constructor .

It's that simple , Don't think about other things , Whether it works or not is the key .

3.2 Why?

Return directory

Why Promise

Look at a piece of code :

const action = () => {
  setTimeout(() => {
    ajax('http://www.xxx.com/getData', (text) => {
      if (text === 'hello') {
        doSomething2();
      } else if (text === 'world') {
        doSomething3();
      }
    })
  }, 500);
};
action();

doSomething1();

This is called back to hell code :

  1. perform action, take setTimeout Put in the macro task queue
  2. perform doSomething1(), Execute the code inside
  3. 500ms Or later , perform ajax, Waiting for completion
  4. ajax After completion , Judge text, And then perform doSomething2() perhaps doSomething3.

It certainly doesn't seem easy , Because when doSomething The code inside will be enriched again , You don't look carefully , I don't know how this code will go .

Let's do another example :

 request 1(function( Request the results 1){
   request 2(function( Request the results 2){
     request 3(function( Request the results 3){
       request 4(function( Request the results 4){
         request 5(function( Request the results 5){
           request 6(function( Request the results 3){
            ...
          })
        })
      })
    })
  })
})

Do you feel numb on your scalp .

The negative effects of callback to hell are as follows :

  • Code bloated .
  • Poor readability .
  • The coupling is too high , Poor maintainability .
  • Poor code reusability .
  • Easy to breed bug.
  • Exceptions can only be handled in callbacks .

therefore , To deal with this pain , This requires a commitment :

  • Give something to someone , When this man is done , Failure or success , Will give you a response , So that you can safely leave it to it .

This man is called Promise, Let's take a look at its intuitive function :

function getData() {
  const p = new Promise((resolve, reject) => {
    // Ajax  Request etc. 
    setTimeout(() => {
      console.log(' Data acquisition success ');
      resolve(' Data after successful input ');
    }, 1000);
  });
  return p;
}
getData().then((res) => {
  //  Get data , And then deal with it 
  console.log(res);

  //  If there's still  Ajax  request , So keep calling 
  // getData2()
});

So we can play with ease .

3.3 How to use it?

Return directory

Promise Use , It's not hard to say , Let's go straight to the code :

// 1.  Set up a  promise
const promise = new Promise((resolve, reject) => {
  // 2.  Set up a  0-10  random number 
  const number = Math.floor(Math.random() * 10);

  // 3.  If this number is greater than  5, Let's take it as a success 
  if (number > 5) {
    resolve(' Greater than  5'); // resolve  It means to solve 
  } else { // 4.  Otherwise, it will be a failure 
    reject(' Less than  5'); // reject  It means to deal with failure 
  }
});

// 5.  If it is  resolve, Then go  .then; If it is  reject, Then go  .catch
promise.then((res) => {
  console.log(' success :', res);
}).catch((error) => {
  console.log(' Failure :', error);
}).finally(() => {
  // 6.  Be careful  finally  It means the end of the play , Whether it's a good ending or a bad ending , It's the end 
  console.log(' No matter what happened ahead , I will call ');
});

Its output :

Output 1
 Failure :  Less than  5
 No matter what happened ahead , I will call 
Output 2
 success :  Greater than  5
 No matter what happened ahead , I will call 

Because we use random values , So the above 2 All kinds of outputs are possible .

As for the... In it resolvereject.then().catch().finally(), We don't care about , I'll talk about it later , Just ask yourself if you understand the previous one ?

If you understand , So congratulations on Promise With a simple understanding .

Four Promise Basics

Return directory

4.1 new Promise

Return directory

First , Let's take a look at how to walk a new Promise

const promise = new Promise((resolve, reject) => {
  console.log(resolve); // [Function]
  console.log(reject); // [Function]
});

console.log(promise); // Promise { <pending> }

then , We distinguish these concepts :

  1. Promise An object is a constructor , Used to generate Promise example , therefore new Promise() Not surprisingly enough .
  2. new Promise() Pass in a function , This function can take 2 Parameters :resolve and reject.
  3. resolve The role of the Promise Object state from “ Hang in the air ” Turn into “ success ”(pending -> resolved
  4. reject The role of the Promise Object state from “ Hang in the air ” Turn into “ Failure ”(pending -> rejected
  5. No execution at resolve and reject Before , They're still pending Of .

Last , It must be said that , My friends have a clear idea of this .

So let's take a look at Promise The state of .

4.2 Promise state

Return directory

Promise Yes 3 States :pendingfulfilledrejected

  1. The initial state :pending
  2. Success status :fulfilled( The actual print will see resolved
  3. Failure status :rejected

If you are in the new Promise Used in China resolve(), Then it will go .then();

If you're using a reject(), Then it goes .catch().

How to put it? ?

const promise1 = new Promise((resolve, reject) => {
  resolve(' success ');
});

promise1.then((res) => {
  console.log('res 1:', res);
}).catch((error) => {
  console.log('error 1:', error);
})

const promise2 = new Promise((resolve, reject) => {
  reject(' Failure ');
});

promise2.then((res) => {
  console.log('res 2:', res);
}).catch((error) => {
  console.log('error 2:', error);
})

In this code , Its output is :

res 1:  success 
error 2:  Failure 

It's easy to understand , because promise1 go resolve and promise2 go reject.

Promise Once the state of is changed, it cannot be changed again .

Look at the code below :

const promise = new Promise((resolve, reject) => {
  resolve(' success  1');
  reject(' Failure ');
  resolve(' success  2');
});

promise.then((res) => {
  console.log('res:', res);
}).catch((err) => {
  console.log('err:', err);
});

Output what ?

Yes, the output is :res: success 1.

a promise is weightier than one thousand bars of gold , You agreed to introduce your sister to me , I'll tell you later , How can this be done .

Crazy hints

Again ,Promise It's not allowed to return :

  • You change the status to resolved, Then don't try to change it , Let's go .then() Well !

OK, See here, you're right Promise The foundation has a certain understanding , Let's go to the question !

5、 ... and Question bank : Basic questions

Return directory

before this , Once again Event Loop.

Event Loop Execution order :

  1. At first, the whole script script Execute as a macro task
  2. In the process of execution , Synchronization code Direct execution , Macro task Enter the macro task queue , Micro task Enter the micro task queue .
  3. The current macro task is out of the team , Check the list of micro tasks , If there is one, execute it in turn , Until it's all done .
  4. Execute browser UI Rendering of threads .
  5. Check if there is Web Worker Mission , If there is one, carry out .
  6. Finish this round of macro tasks , Back to step 2, In turn, cycle , Until the macro and micro task queues are empty .

Micro task Include :

  • MutationObserver
  • Promise.then()/catch()
  • With Promise Other technologies developed for the foundation , for example fetch API
  • V8 The garbage collection process
  • Node Unique process.nextTick

Macro task Include :

  • script
  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI rendering

For example, a piece of code :

const promise = new Promise((resolve, reject) => {
  console.log('1');
  resolve('2');
});

setTimeout(() => {
  console.log('3');
}, 0);

promise.then((res) => {
  console.log(res);
});

Output :1 -> 2 -> 3.

How do you understand that ?

At the beginning of all tasks , Because macro tasks include script, So the browser will first perform a macro task , The delayed tasks you see in the process ( for example setTimeout) It will be executed in the next macro task .
  1. Go ahead script.
  2. meet promise = new Promise, Go straight inside .
  3. Print out 1.
  4. meet resolve(), take Promise Status changed to resolved, take Promise.then() throw sth. into script In the micro task queue under this macro task .
  5. here script The micro task queue under macro task includes :promise.then().
  6. meet setTimeout(), Put it in the macro task queue .
  7. At this point, the macro task queue has :scriptsetTimeout.
  8. Synchronization task completed .
  9. Check the current macro task script Next micro task , And circle out of the team .
  10. Output 2.
  11. Macro task script There's nothing that can be executed , Go to the next macro task setTimeout.
  12. Output 3.
  13. The macro task queue is finished , Code execution completed .

Simply speaking :

  1. Go ahead script.
  2. Macro tasks encountered setTimeout Wait for the back , etc. script Go out of the team after you've gone .
  3. See the current macro task for the micro task encountered , yes script Just throw it away script Inside , yes setTimeout Just throw it away setTimeout Inside .
  4. Each macro task completes the synchronization task and the micro task , Just go to the next macro task .
  5. Cycle steps 4.

It's that simple , It's no use saying more , Brush the title to deepen my impression !

5.1 Topic 1

Return directory
const promise = new Promise((resolve, reject) => {
  console.log('promise');
});

console.log('1', promise);

/*
   The output sequence is analysis :
   Output :
    * promise
    * 1 Promise { <pending> }
   analysis :
    1.  From top to bottom , meet  new Promise, Output  'promise'
    2.  Output  '1'  and  promise  current state 
*/

5.2 Topic two

Return directory
const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve('success');
  console.log(2);
});

promise.then(() => {
  console.log(3);
})

console.log(4);

/**
   Output process and Analysis :
   Output :1 -> 2 -> 4 -> 3
   analysis :
    1.  From the top down , meet  new Promise, Go ahead  1
    2.  meet  resolve, change  Promise  state 
    3.  Output  2
    4.  meet  .then(), Throw it into a micro task 
    5.  Output  4
    6.  Come back to the steps  4  The micro task of , Output  3
*/

5.3 Topic three

Return directory
const promise = new Promise((resolve, reject) => {
  console.log(1);
  console.log(2);
});

promise.then(() => {
  console.log(3);
})

console.log(4);

/**
   Output process and Analysis :
   Output :1 -> 2 -> 4
   analysis :
    1.  From the top down , meet  new Promise, Go ahead  1
    2.  Keep going , Output  2
    3.  meet  .then(), because  new Promise  Not in China  resolve, So you don't throw it into a micro task 
    4.  Output  4
*/

5.4 Topic four

Return directory
const promise1 = new Promise((resolve, reject) => {
  console.log('promise1');
  resolve('resolve1');
})

const promise2 = promise1.then((res) => {
  console.log(res);
});

console.log('1', promise1);
console.log('2', promise2);

/**
   Output sequence and Analysis :
   Output :
    * promise1
    * 1 Promise { <resolve>: 'resolve1' }
    * 2 Promise { <pending> }
    * resolve1
   analysis :
    1.  meet  new Promise, Output  promise1
    2.  meet  resolve, change  Promise  state , And save the results 
    3.  meet  promise1.then, Put it in the micro task queue 
    4. promise2  It's a new state of being  pending  Of  Promise
    5.  Output  1  and  promise1, At present  promise1  The status of is  resolve, And it exists  'resolve1'
    6.  Output  2  and  promise2, At present  promise2  The status of is  peding
    7.  Macro task finished , Perform micro tasks , Output  resolve1
*/

5.5 Topic 5

Return directory
const fn = () => (new Promise((resolve, reject) => {
  console.log(1);
  resolve('success');
}));

fn().then((res) => {
  console.log(res);
})

console.log('start');

/**
   Execution order and parsing :
   The order :
    * 1
    * 'start'
    * 'success'
   analysis :
    1. fn  Is an immediate execution function , So it's going to execute first  new Promise, So the output  1
    2.  meet  resolve, take  Promise  State change 
    3.  meet  .then(), Because the front changed the State , So it's going to be put into micro tasks 
    4.  Output  'start'
    5.  Macro task finished , Perform micro tasks , Output  'success'
*/

5.6 Topic 6

Return directory
const fn = () => {
  return new Promise((resolve, reject) => {
    console.log(1);
    resolve('success');
  })
};

console.log('start');

fn().then((res) => {
  console.log(res);
});

/**
   Execution order and parsing :
   The order :
    * 'start'
    * 1
    * 'success'
   analysis :
     The last problem is to execute the function immediately , The problem is not 
     So in the  fn()  When called , Will execute  new Promise
*/

6、 ... and Question bank : combination setTimeout

Return directory

About macro tasks setTimeout, We are going to give an example of a classic problem :

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 0);
}

The output of this problem :

3
3
3

from Event Loop From the perspective of :

  1. Take the synchronous task ,var i The traversal is finished ,i = 3var Variable pollution ).
  2. for() While traversing , take 3 individual setTimeout Into the macro task .
  3. script This macro task is finished .
  4. Execute sequentially 3 individual setTimeout, Because at this time i by 3, So it will output in turn 3 individual 3.

Of course , The solution is simple :

  • Method 1 : Set immediate execution function

By setting the way the function is executed immediately , Form a block scope , solve i The pollution problem of .

for (var i = 0; i < 3; i++) {
  (function(i) {
    setTimeout(() => {
      console.log(i);
    }, 0);
  })(i);
}
  • Method 2 : Set up let

let Will make for Form a block scope , To prevent pollution , solve the problem .

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 0);
}

Of course ,setTimeout There's another problem :

setTimeout(() => {
  console.log(1);
}, 0);

setTimeout(() => {
  console.log(2);
}, 1000);

setTimeout(() => {
  console.log(3);
}, 500);

What does this code output ?

1
3
2

setTimeout receive 2 Parameters :

  • function(): Callback function . Execute after the time specified by the second parameter .
  • timer: execution time ( millisecond ). stay n The callback function is executed in milliseconds .

Generally speaking , Macro tasks follow the rules of the queue , Come in and out in order , This should output :1 -> 2 -> 3.

This is in timer It's true under the same circumstances .

however , stay timer In different situations , Need to follow Priority queue The way to join the team :

  • Who is the youngest , Who is in front .

So the order of output here is :1 -> 3 -> 2.

You don't need to understand Priority queue What is it , You want to respect the old and love the young , timer The smaller, the more ahead .

OK, About setTimeout Related knowledge jsliang Introduction completed , Let's look at the problem !

6.1 Topic 1

Return directory
console.log('start');

setTimeout(() => {
  console.log('time');
});

Promise.resolve().then(() => {
  console.log('resolve');
});

console.log('end');

/**
   Execution sequence and Analysis :
   The order :
    * 'start'
    * 'end'
    * 'resolve'
    * 'time'
   analysis :
    1.  remember  script  and  setTimeout  It's a macro task 
    2.  First, execute  script
    3.  Output  'start'
    4.  meet  setTimeout, Put it in the macro task queue 
    5.  meet  Promise, then  Promise  become  resolve()  Post state , Yes  .then(), So put it in the micro task queue 
    6.  Output  'end'
    7.  Traverse this micro task queue , The output step  5  The content of , namely  'resolve'
    8.  step  7  Walk the , Execute the next macro task queue , Output  'time'
*/

6.2 Topic two

Return directory
const promise = new Promise((resolve, reject) => {
  console.log(1);
  
  setTimeout(() => {
    console.log('timerStart');
    resolve('success');
    console.log('timerEnd');
  }, 0);

  console.log(2);
});

promise.then((res) => {
  console.log(res);
});

console.log(4);

/**
   Execution sequence and Analysis :
   The order :
    * 1
    * 2
    * 4
    * 'timerStart'
    * 'timerEnd'
    * 'success'
   analysis :
    1.  remember  script  and  setTimeout  It's a macro task 
    2.  First, execute  script  This macro task 
    3.  meet  new Promise, Output  1
    4.  meet  setTimeout, Put in the macro task queue 
    5.  Output  2
    6.  meet  .then(), But there's no key (resolve), skip 
    7.  Output  4
    8.  Currently, there are no micro tasks , Execute the next macro task  setTimeout
    9.  Output  'timerStart'
    10. Promise  meet  resolve, Change state , indicate  .then()  It's time to put in micro tasks 
    11.  Output  'timerEnd'
    12.  Execute macro task  setTimeout  Next micro task , namely  Promise.then()
    13.  Output  'success'
*/

6.3 Topic three

Return directory
setTimeout(() => {
  console.log('timer1');
  setTimeout(() => {
    console.log('timer3');
  }, 0);
}, 0);

setTimeout(() => {
  console.log('timer2');
}, 0);

console.log('start');

/**
   Execution sequence and Analysis :
   The order :
    * 'start'
    * 'timer1'
    * 'timer2'
    * 'timer3'
   analysis :
    1.  remember  script  and  setTimeout  It's a macro task 
    2.  First, execute  script  This macro task 
    3.  Meet the first one  setTimeout, Put it in the macro task queue 
    4.  there  setTimeout For export  'timer1'  A whole of  setTimeout, At this point, it doesn't go into it to execute code 
    5.  Meet the second one  setTimeout, Put it in the macro task queue 
    6.  Output  'start'
    7.  Look at micro tasks , There are no micro tasks 
    8.  View macro task queue , Yes  2  individual , They are output  time1  and  timer2  Of 
    9.  First of all  setTimeout  Outgoing queue , Output  'timer1'
    10.  Meet the third one  setTimeout, Put it in the macro task queue , After the second 
    11.  first  setTimeout  No micro tasks , So this macro task is finished 
    12.  the second  setTimeout  Outgoing queue , Output  'timer2'
    13.  It doesn't use micro tasks at this point , So this macro task is finished again 
    14.  Third  setTimeout  Outgoing queue , Output  'timer3'
    15.  The third one doesn't work either , So it's done 
    16.  At this point, the macro task queue is executed , Call it a day 
*/

6.4 Topic four

Return directory
setTimeout(() => {
  console.log('timer1');
  Promise.resolve().then(() => {
    console.log('promise');
  });
}, 0);

setTimeout(() => {
  console.log('timer2');
}, 0);

console.log('start');

/**
   Execution sequence and Analysis :
   The order :
    * 'start'
    * 'timer1'
    * 'promise'
    * 'timer2'
   Be careful :node V10.16.0  The output version of is different 
   analysis :
    1.  remember  script  and  setTimeout  It's a macro task 
    2.  First, execute  script  This macro task 
    3.  Meet the first one  setTimeout, Put it in the macro task queue 
    4.  there  setTimeout For export  'timer1'  A whole of  setTimeout, At this point, it doesn't go into it to execute code 
    5.  Meet the second one  setTimeout, Put it in the macro task queue 
    6.  Output  'start'
    7.  Look at micro tasks , There are no micro tasks , So execute the next macro task 
    8.  View macro task queue , Yes  2  individual , They are output  time1  and  timer2  Of 
    9.  First of all  setTimeout  Outgoing queue , Output  'timer1'
    10.  meet  Promise.then(), Put it in the micro task queue at this time 
    11.  step  10  The first one is stored  setTimeout  A micro task of , Execute and output  'promise'
    12.  the second  setTimeout  Outgoing queue , Output  'timer2'
    13.  It doesn't use micro tasks at this point , So this macro task is finished again 
    14.  At this point, the macro task queue is executed , Call it a day 
*/

6.5 Topic 5

Return directory
Promise.resolve().then(() => {
  console.log('promise1');
  const timer2 = setTimeout(() => {
    console.log('timer2');
  }, 0);
});

const timer1 = setTimeout(() => {
  console.log('timer1');
  Promise.resolve().then(() => {
    console.log('promise2');
  });
}, 0);

console.log('start');

/**
   Execution sequence and Analysis :
   The order :
    * 'start'
    * 'promise1'
    * 'timer1'
    * 'promise2'
    * 'timer2'
   analysis :
    1.  remember  script  and  setTimeout  It's a macro task 
    2.  First, execute  script  This macro task 
    3.  meet  Promise.then(), Push it into the micro task queue , Be careful not to execute the contents 
    4.  meet  timer1, Push it to the macro task queue 
    5.  Output  'start'
    6.  see  script  Macro task queue in , Find out  Promise.then(), Push it out for execution 
    7.  Output  'promise1'
    8.  meet  timer2, Push it to the macro task queue 
    9. script  There are no remaining micro tasks , So continue to traverse the macro task 
    10.  Discovery queue  [timer1, timer2], According to the first in first out principle , Introduction  timer1
    11.  Output  'timer1', Discover micro tasks  Promise.then(), Push it forward  timer1  Micro task queue of 
    12.  Output  `promise2`
    13.  Continue to execute macro task queue , Out of the team  timer2, Output  'timer2'
*/

6.6 Topic 6

Return directory
const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success');
  }, 0);
});

const promise2 = promise1.then(() => {
  throw new Error('error!');
});

console.log('promise1-1', promise1);
console.log('promise2-1', promise2);

setTimeout(() => {
  console.log('promise1-2', promise1);
  console.log('promise2-2', promise2);
}, 0);

/**
   Execution sequence and Analysis :
   The order :
    * 'promise1-1' Promise { <pending> }
    * 'promise2-1' Promise { <pending> }
    * 'promise1-2' Promise { <resolve>: 'success' }
    * 'promise2-2' Promise { <reject>: Error: error! }
   Be careful : stay  Node v10.16.0  The result of running on is different 
   analysis :
    1.  remember  script  and  setTimeout  It's a macro task 
    2.  First, execute  script  This macro task 
    3.  meet  promise1  here , perform  new Promise  What's in it , Will bring  resolve  Of  setTimeout  Push macro task queue 
    4.  meet  promise2, Because I haven't entered yet  resolve  state , So here we ignore 
    5.  Two consecutive lines of output , because  promise1  and  promise2  They haven't been dealt with yet , So it is  peading  state 
    6.  Meet the second one  setTimeout, Push it into the macro task queue 
    7.  View macro task queue , Launch the first  setTimeout, take  Promise  Status changed to  resolve
    8.  perform  promise2, change  promise2  The status of is  reject
    9.  first  setTimeout  completion of enforcement , Execute the second  setTimeout
    10.  The output step  8  and   step  9  Medium  Promise  state 
*/

6.7 Topic 7

Return directory
const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success');
    console.log('timer1');
  }, 0);

  console.log('promise1  What's in it ');
});

const promise2 = promise1.then(() => {
  throw new Error('error!');
});

console.log('promise1-1', promise1);
console.log('promise2-1', promise2);

setTimeout(() => {
  console.log('timer2');
  console.log('promise1-1', promise1);
  console.log('promise2-2', promise2);
}, 0);

/**
   Execution sequence and Analysis :
   The order :
    * 'promise1  What's in it '
    * 'promise1-1' Promise { <pending> }
    * 'promise2-1' Promise { <pending> }
    * 'timer1'
    * 'timer2'
    * 'promise1-2' Promise { <resolve>: 'success' }
    * 'promise2-2' Promise { <reject>: Error: error! }
   Be careful : stay  Node v10.16.0  The result of running on is different 
   analysis :
     The type of the following question is similar , I'm not going to do the analysis here 
*/

7、 ... and .then() Chain operation

Return directory

7.1 Two parameters

Return directory

In the title above , We got to know .then(), But we didn't go into details , So here we will explain them one by one .

Don't talk much , Look at the code first :

const promise1 = new Promise((resolve, reject) => {
  resolve('1');
});

promise1.then(
  (res) => {
    console.log('res:', res);
  }, (err) => {
    console.log('err:', err);
  }
)

const promise2 = new Promise((resolve, reject) => {
  reject('1');
});

promise2.then(
  (res) => {
    console.log('res:', res);
  }, (err) => {
    console.log('err:', err);
  }
)

What does it output :

res: 1
err: 1

therefore , actually .then() It's reception 2 Parameters :

  • resolved: If we set it up resolved state , Then we'll take the first parameter .
  • rejected: If we set it up rejected state , Then we'll take the second parameter .

This is the first 2 Parameters and .catch() It's almost the same .

however , To keep the code sizable , It is suggested that the second parameter be changed to .catch(), Easy to understand .

7.2 call chaining

Return directory

stay Promise.then() In the method ,.then() It can be called in chain .

Promise.resolve(1).then((res1) => {
  console.log('res 1:', res1); // res 1: 1
  return res1;
}).then((res2) => {
  console.log('res 2:', res2); // res 2: 1
})

You can see , next .then(), You can receive the last one .then() in return What's coming out .

Of course , It is worth noting that , If we don't return res1, So the output becomes :res 2: undefined.

such , If we need to do some asynchronous operations , Then you can use this method .

Don't talk much , On the first code :

const red = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(' red ');
      resolve(' The red light is over ');
    }, 1000);
  });
}
const green = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(' green ');
      resolve(' The green light is gone ');
    }, 1000);
  });
}

red().then((res1) => {
  console.log('res1:', res1);
  return green();
}).then((res2) => {
  console.log('res2:', res2);
})

/*
  1s  Post output :
     red 
    res1:  The red light is over 

  2s  Post output :
     green 
    res2:  The green light is gone 
*/

Here , Red light back to a Promise object , etc. setTimeout Walk the , The status changes to resolved, Then go .then(), then 1s Post output : red -> res1: The red light is over .

next , We will green() Yes , And return it to return To the next one .then().

therefore , We will be in 2s Post output green -> The green light is gone .

This is it. .then() The door of the road .

8、 ... and .catch() Capture problem

Return directory

We mentioned above :

  • reject The role of the Promise Object state from “ Hang in the air ” Turn into “ Failure ”(pending -> rejected

and .then() Of the 2 Parameters and .catch() It's the same thing , It's all about capturing failed content .

const getRandom = new Promise((resolve, reject) => {
  const number = Math.random() * 10; //  Generate  1-10  Number of ranges 
  if (number > 5) {
    reject(' Number exceeds  5');
  } else {
    resolve(' Number less than  5');
  }
});

//  Capture error mode one : Use  catch()
getRandom.then((res) => {
  console.log('res:', res);
}).catch((error) => {
  console.log('error:', error);
});

//  Capture error mode 2 :then()  There are two parameters 
getRandom.then(
  (res) => { //  Equate to  then()
    console.log('res:', res);
  }, (error) => { //  Equate to  catch()
    console.log('error:', error);
  },
);

/*
  Output :

  * res:  Number less than  5
  * error:  Number exceeds  5
  
   Random one of the two 
*/

Of course , In order to read well , Recommended or used .then().catch() The way , Not through .then() The inside number 2 Parameters to represent .

Nine .finally() Enforcement

Return directory

finally Method is used to specify whether Promise What is the final state of the object , Will perform the operation .

meanwhile ,.finally() Method does not take any arguments , Because it's enforcement , Don't rely on Promise The results of the implementation of .

It's essentially .then() A special case of the method .

// 1.  Set up a  promise
const promise = new Promise((resolve, reject) => {
  // 2.  Set up a  0-10  random number 
  const number = Math.floor(Math.random() * 10);

  // 3.  If this number is greater than  5, Let's take it as a success 
  if (number > 5) {
    resolve(' Greater than  5'); // resolve  It means to solve 
  } else { // 4.  Otherwise, it will be a failure 
    reject(' Less than  5'); // reject  It means to deal with failure 
  }
});

// 5.  If it is  resolve, Then go  .then; If it is  reject, Then go  .catch
promise.then((res) => {
  console.log(' success :', res);
}).catch((error) => {
  console.log(' Failure :', error);
}).finally(() => {
  // 6.  Be careful  finally  It means the end of the play , Whether it's a good ending or a bad ending , It's the end 
  console.log(' No matter what happened ahead , I will call ');
});

Let's take the code at the beginning to review .finally() Well :

Output 1
 Failure :  Less than  5
 No matter what happened ahead , I will call 
Output 2
 success :  Greater than  5
 No matter what happened ahead , I will call 

Because we use random values , So the above 2 All kinds of outputs are possible .

however , No matter what kind of output ,.finally() It will come out .

Ten Question bank :.then()、.catch()、.finally()

Return directory

10.1 Topic 1

Return directory
const promise = new Promise((resolve, reject) => {
  resolve('success1');
  reject('error');
  resolve('success2');
});

promise.then((res) => {
  console.log('then1: ', res);
}).then((res) => {
  console.log('then2: ', res);
}).catch((error) => {
  console.log('catch: ', error);
});

/**
   Execution sequence and Analysis :
   The order :
    * 'then1: success1'
    * 'then2: undefined'
   analysis :
    1.  Yes  resolve('success1')  after , Changed the state to  resolve, Ignore  new Promise  hinder 
    2.  Will be the first  1  individual  .then()  Add to micro task 
    3.  Execution section  1  individual  .then(), Will be the first  2  individual  .then()  Promoting micro tasks 
*/

10.2 Topic two

Return directory
const promise = new Promise((resolve, reject) => {
  reject('error');
  resolve('success2');
});

promise.then((res) => {
  console.log('then1: ', res);
}).then((res) => {
  console.log('then2: ' ,res);
}).catch((error) => {
  console.log('catch: ', error);
}).then((res) => {
  console.log('then3: ', res);
})

/**
   Execution sequence and Analysis :
   The order :
    * 'catch:  error'
    * 'then3:  undefined'
   analysis :
    1.  meet  new Promise(), take  reject('error')  perform , change  Promise  The state of 
    2.  meet  .catch(), Push it into micro tasks 
    3.  perform  .catch()  What's in it , Output  'catch: error', then  return Promise {<pending>}
    4.  Perform the next micro task  .then(), Output  then3: undefined
*/

10.3 Topic three

Return directory
Promise
.resolve(1)
.then((res) => {
  console.log(res);
  return 2;
}).catch((err) => {
  return 3;
}).then((res) => {
  console.log(res);
});

/**
   Execution sequence and Analysis :
   The order :
    * 1
    * 2
   analysis :
    1. resolve(1)  The first one  .then, Print  1
    2. return 2  It's going to be packaged as  resolve(2)
    3.  Because no  reject, So don't go  .catch
    4.  Finish the first  2  individual  .then, Print  2
*/

10.4 Topic four

Return directory
Promise
.reject(1)
.then((res) => {
  console.log(res);
  return 2;
}).catch((err) => {
  console.log(err);
  return 3;
}).then((res) => {
  console.log(res);
});

/**
   Execution sequence and Analysis :
   The order :
    * 1
    * 3
   analysis :
    1. reject(1)  Will go  .catch, So first output  1
    2. return 3  It's going to be packaged as  resolve(3)
    3.  So keep going  2  individual  .then, Output  3
*/

10.5 Topic 5

Return directory
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('timer');
    resolve('success');
  }, 0);
});

const start = Date.now();

promise.then((res) => {
  console.log(res, Date.now() - start);
});

promise.then((res) => {
  console.log(res, Date.now() - start);
});

/**
   Execution sequence and Analysis :
   The order :
    * 'timer'
    * 'success 4'
    * 'success 4'
   notes : Also have  3/4  perhaps  4/5  The situation of 
   analysis :
    1. new Promise  take  setTimeout  Add to macro task 
    2.  After executing the macro task  script, And then execute  setTimeout
    3.  Output  'timer'
    4.  Mark  Promise  Status as  resolve
    5.  The first one.  .then()  Put in micro tasks 
    6.  Put the second  .then()  Put in micro tasks 
    7.  Because of the steps  5  And steps  6  When , Both are the same  resolve  value , So it's all  'success'
    8.  Output  success 4
    9.  Output  success 4
    10.  If the execution is slow , Then the values of the two outputs will be inconsistent . for example  3、4
*/

10.6 Topic 6

Return directory
Promise.resolve().then(() => {
  return new Error('error!');
}).then((res) => {
  console.log('then: ', res);
}).catch((err) => {
  console.log('catch: ', err);
});

/**
   Execution sequence and Analysis :
   The order :
    * 'then:  Error: error!'
   analysis :
    return new Error('error!')  Will be wrapped up in  return Promise.resolve(new Error('error!'))  Back to  .then()
*/

10.7 Topic 7

Return directory
const promise = Promise.resolve().then(() => {
  return promise;
});

promise.catch((err) => {
  console.log(err);
});

/**
   Execution sequence and Analysis :
   The order :
    * TypeError: Chaining cycle detected for promise #<Promise>
   analysis :
     Can't return  promise  In itself , It's going to create a dead cycle 
*/

10.8 Topic 8

Return directory
Promise
.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log);

/**
   Execution sequence and Analysis :
   The order :
    * 1
   analysis :
    1. .then  and  .catch  The parameter of is expected to be a function , Pass through of values occurs when non functions are passed in 
    2.  Value transmission leads to  1  individual  then  And the  2  individual  then  It's not a function , That led it to the last  1  individual  then  Inside 
*/

10.9 Topic nine

Return directory
Promise
.reject('err')
.then((res) => {
  console.log('success: ', res);
}, (err) => {
  console.log('error: ', err);
}).catch((err) => {
  console.log('catch: ', err);
})

/**
   Execution sequence and Analysis :
   The order :
    * 'error:  err'
   analysis :
    reject('err')  Will enter  Promise.then  Second parameter of , So the output  'error: err'
*/

If .then() No 2 Parameters are removed , Then it will enter .catch() Function .

10.10 Topic ten

Return directory
Promise
.resolve()
.then((res) => {
  throw new Error('error!');
}, (err) => {
  console.log('error: ', err);
}).catch((err) => {
  console.log('catch: ', err);
})

/**
   Execution sequence and Analysis :
   The order :
    * catch:  Error: error!
   analysis :
     the reason being that  .resolve(), So it will execute  .then  The first  1  Parameters , then  return  Value to  .catch  in 
     Instead of going back to  2  On one parameter 
*/

10.11 Topic eleven

Return directory
  1. .finally() No matter what the method is Promise The object's final state is executed .
  2. .finally() Method does not accept any parameters , That means you're in .finally() There is no way to know Promise The final state is resolved still rejected Of .
  3. The default it eventually returns will be the last one Promise The object is worth , However, if an exception is thrown, the exception is returned Promise object .
Promise
.resolve('1')
.then((res) => {
  console.log(res);
}).finally(() => {
  console.log('finally1');
});

Promise
.resolve('2')
.finally(() => {
  console.log('finally2');
  return ' Here is  finally2';
}).then((res) => {
  console.log('finally2  hinder  then  function ', res);
})

/**
   Execution sequence and Analysis :
   The order :
    * 1
    * 'finally2'
    * 'finally1'
    * 'finally2  hinder  then  function  2'
   analysis :
*/

10.12 Topic twelve

Return directory
Promise
.resolve('1')
.finally(() => {
  console.log('finally1');
  return new Error(' I am a  finally1  Exception thrown in ');
}).then((res) => {
  console.log('finally  hinder  then  function : ', res);
}).catch((err) => {
  console.log(' Capture the error : ', err);
})

/**
   Execution sequence and Analysis :
   The order :
    * 'finally1'
    *  Capture the error :  Error:  I am a  finally1  Exception thrown in 
   analysis :
    1.  meet  resolve('1'), take  Promise  Change the status of  resolve
    2.  meet  .finally(), Into the micro task , Back  .then()  and  .catch()  Need to wait  .finally()  completion of enforcement 
    3.  perform  .finally(), Output  'finally1', And then execute  throw new Error, This situation will be handed over to  .catch()
    4.  Output   Capture the error :  Error:  I am a  finally1  Exception thrown in 
   Add :
     If this is  return throw new Error('')  What's going to happen ?
     It will go  .then(), Because it is  return  In the form of , So as to output :finally  hinder  then  function : 1
     Notice the  return new Error('')  There is no return function , therefore  1  Through 
*/

10.13 Topic thirteen

Return directory
function promise1() {
  let p = new Promise((resolve) => {
    console.log('promise1');
    resolve('1');
  });
  return p;
}

function promise2() {
  return new Promise((resolve, reject) => {
    reject('error');
  });
}

promise1().then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
}).finally(() => {
  console.log('finally1');
})

promise2().then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
}).finally(() => {
  console.log('finally2');
})

/**
   Execution sequence and Analysis :
   The order :
    * 'promise1'
    * '1'
    * 'error'
    * 'finally1'
    * 'finally2'
   analysis :
    1.  perform  promise1(), Enter the code inside 
    2.  meet  p, take  p  The content is executed again , Print  'promise1', At the same time, change its status to  resolve
    3.  here  promise1()  take  .then()  This micro task advances the micro task queue , We record it as micro  1
    4.  step  1  To  3,promise1()  completion of enforcement 
    5.  Start execution  promise2(), meet  return new Promise, Change its status to  reject
    6.  meet  promise2()  Medium  .then(), Push it into the micro task queue , Recorded as micro  2
    7. script  This macro task is finished , Start executing the micro task queue 
    8.  Launch micro  1, Print  '1', Because it's from above  p  yes  resolve('1')
    9.  take  promise1()  Inside  finally1  Push the micro task queue , Recorded as micro  3
    10.  Launch micro  2, Because when you mark the front , The value of transmission is  'error', So we output  'error'
    11.  Launch micro  3, Output  'finally1'
    12.  Launch micro  4, Output  'finally2'
*/

10.14 Topic fourteen

Return directory
function promise1() {
  let p = new Promise((resolve) => {
    console.log('promise1');
    resolve('1');
  });
  return p;
}

function promise2() {
  return new Promise((resolve, reject) => {
    reject('error');
  });
}

promise1().then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
}).then(() => {
  console.log('then1');
})

promise2().then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
}).then(() => {
  console.log('then2');
})

/**
   Execution sequence and Analysis :
   The order :
    * 'promise1'
    * '1'
    * 'error'
    * 'then1'
    * 'then2'
   analysis :
     The derivation process is the same as the problem 
*/

11、 ... and .all() Relay race

Return directory

Promise Of all Methods provide the ability to perform asynchronous operations in parallel , And the callback is executed after all asynchronous operations have been executed .

Suppose there's code :

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

p The status of the p1p2p3 decision , There are two cases .

  1. Only p1p2p3 The state of fulfilled,p The state of fulfilled, here p1p2p3 The return value of consists of an array , Pass to p Callback function for .
  2. as long as p1p2p3 One of them was rejected,p The state of rejected, At this time, the first was reject The return value of the instance of , Will pass to p Callback function for .

therefore , Combine it with setTimeout As an asynchronous function , Let's try to use .all() Method :

const one = new Promise((resolve) => {
  setTimeout(() => {
    console.log('one');
    resolve('one');
  }, 1000);
}) 
const two = new Promise((resolve) => {
  setTimeout(() => {
    console.log('two');
    resolve('two');
  }, 3000);
}) 
const three = new Promise((resolve) => {
  setTimeout(() => {
    console.log('three');
    resolve('three');
  }, 2000);
}) 

/*
  First, the output :
 * one
 * three
 * two
 
  Then the output  res:[ 'one', 'two', 'three' ]
*/
Promise.all([one, two, three]).then((res) => {
  console.log(res); // [ 'one', 'two', 'three' ]
});

This is the success of all States , If this 3 There is 1 One is a failure ? Please try it yourself .

Twelve .race() Individual competition

Return directory

and all() The method is different ,Promise.race() The method is who goes first and outputs first .

It's like an individual running a race 100 It's like the rice race , Nadi 1 Is worth remembering , Don't pay too much attention to the rest .

In the example above ,.all() Change it to .race(), You get different results .

const one = new Promise((resolve) => {
  setTimeout(() => {
    console.log('one');
    resolve('one resolve');
  }, 1000);
}) 
const two = new Promise((resolve) => {
  setTimeout(() => {
    console.log('two');
    resolve('two resolve');
  }, 3000);
}) 
const three = new Promise((resolve) => {
  setTimeout(() => {
    console.log('three');
    resolve('three resolve');
  }, 2000);
}) 

/*
  First, the output  one
  Then the output :one resolve
  Finally, output in order :
 * three
 * two
*/
Promise.race([one, two, three]).then((res) => {
  console.log(res); // 'one'
});

13、 ... and Question bank :.all()、.race()

Return directory

Promise.all() and Promise.race() usage :

  1. .all() The function is to receive a set of asynchronous tasks , Then the asynchronous tasks are executed in parallel , And the callback is executed after all asynchronous operations have been executed .
  2. .race() It also receives a set of asynchronous tasks , Then the asynchronous tasks are executed in parallel , Only the result of the first asynchronous operation that completes is reserved , Other methods are still being implemented , But the results will be discarded .

A small summary :

  1. Promise.all().then() The order of the arrays in the result and Promise.all() The received arrays are in the same order , Not because setTimeout To change the output of .
  2. Promise.all() and Promise.then() When an exception is thrown , They'll only throw out the first problem , By .then() Or the second parameter of .catch() Capture , But it doesn't affect the execution of other asynchronous tasks in the array .

13.1 Topic 1

Return directory

Let's do it before we do it setTimeout Review of knowledge points :

setTimeout(() => {
  console.log('2');
}, 2000);

setTimeout(() => {
  console.log('1-1');
}, 1000);

setTimeout(() => {
  console.log('1-2');
}, 1000);

setTimeout(() => {
  console.log('0');
}, 0);

What is the output of this piece ?

0 -> 1-1 -> 1-2 -> 2

Convenient memory , We can argue that :

  • Both macro tasks , Multiple setTimeout, It can be understood as , The ones with less time will be ranked first .

therefore , Originally, our macro task should be a queue , But just like the one on the top script In macro task , We added 4 individual setTimeout, And this same kind of setTimeout, We sort it by time .

Now let's look at the first question :

function runAsync(x) {
  const p = new Promise((resolved, reject) => {
    if (x % 2 === 0) {
      return setTimeout(() => {
        console.log(x);
        resolved(x);
      }, 2000);
    }
    return setTimeout(() => {
      console.log(x);
      resolved(x);  
    }, 1000);
  });
  return p;
}

Promise.all([
  runAsync(1),
  runAsync(2),
  runAsync(3)
]).then((res) => {
  console.log(res);
})

/**
   Execution sequence and Analysis :
   The order :
    * 1
    * 3
    * 2
    * [1, 2, 3]
   analysis :
    1. Promise.all  take  3  individual  runAsync  Add to the method in order 
    2.  stay  script  In this macro task , Add... In turn  3  individual  setTimeout
    3.  According to the time in the macro task queue  setTimeout  Reorder 
    4. 1、2、3  The corresponding number of seconds is  1s、2s、1s, So the order is  1 -> 3 -> 2
    5.  Wait a second , Output, respectively,  1、3
    6.  Wait for two seconds , Output  2
    7.  perform  .then(), according to  .all()  Output the corresponding array result by sorting the array in ( How to get in and out )
   Applicable scenario :
     You need to preload multiple images 、 Static files, etc , Can pass  Promise.all()  To deal with 
*/

13.2 Topic two

Return directory
function runAsync (x) {
  const p = new Promise((res, rej) => {
    if (x === 3) {
      return setTimeout(() => {
        rej(x, console.log(x));
      }, 500);
    }
    return setTimeout(() => {
     res(x, console.log(x)); 
    }, 1000);
  });
  return p;
}

function runReject (x) {
  const p = new Promise((res, rej) => {
    return setTimeout(() => {
      rej(x, console.log(x));
    }, 1000 * x);
  });
  return p;
}

Promise.all([
  runAsync(1),
  runReject(4),
  runAsync(3),
  runReject(2),
]).then((res) => {
  console.log('then: ', res);
}, (err) => {
  console.log('err: ', err);
}).catch((err) => {
  console.log('catch: ', err);
})

/**
   Execution sequence and Analysis :
   The order :
    * 3
    * err: 3
    * 1
    * 2
    * 4
   analysis :
    1.  First , We should  .all()  It's a queue , fifo 
    2.  At this point, the macro task is added in turn  setTimeout(1)、setTimeout(4)、setTimeout(3)、setTimeout(2)
    3. OK, We said before , identical  setTimeout  Will be sorted , So the order becomes  3 -> 1 -> 2 -> 4
    4.  By this time  setTimeout  The corresponding time is  500ms、1s、2s、4s
    5.  then , There's something new to remember :.catch  Can only capture  .all  The first exception in it , And only once 
    6.  therefore , Execute first  3  When , It will output  3 -> err: 3
    7.  hinder  2  and  4  The exception is no longer thrown , Output... In sequence  1 -> 2 -> 4
*/

13.3 Topic three

Return directory
function runAsync(x) {
  const p = new Promise((resolved, reject) => {
    if (x % 2 === 0) {
      return setTimeout(() => {
        console.log(x);
        resolved(x);
      }, 2000);
    }
    return setTimeout(() => {
      console.log(x);
      resolved(x);  
    }, 1000);
  });
  return p;
}

Promise.race([
  runAsync(2),
  runAsync(1),
  runAsync(3)
]).then((res) => {
  console.log('res: ', res);
})

/**
   Execution sequence and Analysis :
   The order :
    * 1
    * 'res: 1'
    * 3
    * 2
   Be careful :
    Node v10.16.0  The answer is slightly different 
   analysis :
    1. Promise.race()  take  3  individual  runAsync  Add to the method in order 
    2.  stay  script  In this macro task , Add... In turn  3  individual  setTimeout  Macro task :2 -> 1 -> 3
    3.  According to the time in the macro task queue  setTimeout  Reorder 
    4. 1、2、3  The corresponding number of seconds is  1s、2s、1s, So the order is  1 -> 3 -> 2
    5.  Wait a second , Output  1
    6.  here  .race()  Can't wait to tell you the result , Follow the output  res: 1
    7.  Followed by output  3
    8.  Wait for two seconds , Output  2
   Applicable scenario :
     use  race  Set timeout for an asynchronous request , And execute corresponding operation after timeout 
*/

13.4 Topic four

Return directory
function runAsync (x) {
  const p = new Promise((res, rej) => {
    if (x === 3) {
      return setTimeout(() => {
        rej(x, console.log(x));
      }, 500);
    }
    return setTimeout(() => {
     res(x, console.log(x)); 
    }, 1000);
  });
  return p;
}

function runReject (x) {
  const p = new Promise((res, rej) => {
    return setTimeout(() => {
      rej(x, console.log(x));
    }, 1000 * x);
  });
  return p;
}

Promise.race([
  runAsync(1),
  runReject(4),
  runAsync(3),
  runReject(2),
]).then((res) => {
  console.log('then: ', res);
}, (err) => {
  console.log('err: ', err);
}).catch((err) => {
  console.log('catch: ', err);
})

/**
   Execution sequence and Analysis :
   The order :
    * 3
    * err: 3
    * 1
    * 2
    * 4
   analysis :
    1.  First , We should  .race()  It's a queue , fifo 
    2.  At this point, the macro task is added in turn  setTimeout(1)、setTimeout(4)、setTimeout(3)、setTimeout(2)
    3. OK, We said before , identical  setTimeout  Will be sorted , So the order becomes  3 -> 1 -> 2 -> 4
    4.  By this time  setTimeout  The corresponding time is  500ms、1s、2s、4s
    5.  then , Need to remember a little :.race()  Only the one who runs first 
    6.  therefore , Execute first  3  When , It will output  3 -> err: 3
    7.  hinder  2  and  4  The exception is no longer thrown , Output... In sequence  1 -> 2 -> 4
*/

fourteen Promise Source code

Return directory

stay jsliang Handwritten source code series has a detailed analysis .

15、 ... and Question bank : combination async/await

Return directory

summary :

  1. stay function() Come across it await Go straight to the contents .
  2. If function() Inside await There is more code behind , Think of it as Promise.then() equally , As a micro task .

15.1 Topic 1

Return directory
async function async1() {
  console.log(1);
  await async2();
  console.log(2);
}

async function async2() {
  console.log(3);
}

async1();

console.log(4);

/**
   Execution sequence and Analysis :
   The order :
    * 1
    * 3
    * 4
    * 2
   analysis :
    1.  First , We execute  script  This macro task 
    2.  meet  async1(), Execute the code inside , Output  1
    3.  meet  await async2(), blocked , So it needs to be executed first  async2()
    4.  perform  async2(), Output  3
    5.  meet  console.log(4), Output  4
    6.  The blocking part is gone ,script  The macro task is finished , Go on  async1()  hinder 
    7.  Output  2
*/

15.2 Topic two

Return directory
async function async1() {
  console.log('async');

  new Promise((resolve) => {
    console.log('promise');
    resolve();
  }).then((res) => {
    console.log('promise.then');
  })
}

async1();

console.log('start');

/**
   Execution sequence and Analysis :
   The order :
    * 'async'
    * 'promise'
    * 'start'
    * 'promise.then'
   analysis :
    1.  First , We execute  script  This macro task 
    2.  meet  async1(), Execute the code inside , Output  'async'
    3.  meet  new Promise, Execute the code inside , Output  'promise'
    4.  take  Promise  The status of is marked as  resolved
    5.  take  .then()  Into the micro task 
    6.  Output  'start'
    7.  Perform micro tasks  .then(), Output  'promise.then'
*/

15.3 Topic three

Return directory
async function async1() {
  console.log('async1 start');
  setTimeout(() => {
    console.log('timer1 start');
  }, 0);
  Promise.resolve().then((res) => {
    console.log('promise1');
  })
  await async2();
  setTimeout(() => {
    console.log('timer1 end');
  }, 0);
  console.log('async1 end');
}

async function async2() {
  setTimeout(() => {
    console.log('timer2');
  }, 0);
  Promise.resolve().then((res) => {
    console.log('promise2');
  })
  console.log('async2');
}

async1();

console.log('start');

/**
   Execution sequence and Analysis :
   The order :
    * 'async1 start'
    * 'async2'
    * 'start'
    * 'promise1'
    * 'promise2'
    * 'async1 end'
    * 'timer1 start'
    * 'timer2'
    * 'timer1 end'
   analysis :
    1.  First , Let's straighten out the fact that : stay  await  hinder , It will wait until all the micro tasks in the current macro task are completed , And execute 
    2.  meet  async1(), Start executing what's inside 
    3.  Output  'async1 start'
    4.  take  'timer1 start'  Put it in the macro task queue , Mark as macro  1
    5.  take  'promise1'  Into the micro task queue , Marked as micro  1
    6.  meet  await async2(), Execute first  async2, Block the following code , The code after the mark is "after the horse"  1
    7.  perform  async2, meet  'timer2', Put it in the macro task queue , Mark as macro  2
    8.  meet  'promise2', Put it in the micro task queue , Marked as micro  2
    9.  Output  'async2'
    10. async2  Walk the , Keep going down , Output  start
    11.  The current is  3  We didn't leave , The difference is micro  1、 tiny  2  And after the horse  1
    12. 【 memorize mechanically 】, Encounter not to go  11  This situation , We need to remember to perform the current micro task first , After a while 
    13.  Perform micro tasks , Output  'promise1'、'promise2'
    14.  To carry out a post-mortem , take  'timer1 end'  Put it in the macro task queue , This is the macro  3
    15.  Output  'async1 end'
    16.  Execute the macro in turn  1、 macro  2  and   macro  3, Output  'timer1 start' -> 'timer2' -> 'timer1 end'
   Soul ascension :
     If  'timer1 start' -> 'timer2' -> 'timer1 end'  The corresponding time is  500ms、1000ms、500ms, What is the output ?
*/

15.4 Topic four

Return directory
async function async1() {
  console.log('async1 start');
  await async2();
  console.log('async1 end');
  setTimeout(() => {
    console.log('timer1');
  }, 0);
}

async function async2() {
  setTimeout(() => {
    console.log('timer2');
  }, 0);
  console.log('async2');
}

async1();

setTimeout(() => {
  console.log('timer3');
}, 0);

console.log('start');

/**
   Execution sequence and Analysis :
   The order :
    * 'async1 start'
    * 'async2'
    * 'start'
    * 'async1 end'
    * 'timer2'
    * 'timer3'
    * 'timer1'
   analysis :
     The idea is the same as above 
*/

15.5 Topic 5

Return directory
async function fn() {
  return 123;
}

fn().then((res) => {
  console.log(res);
})

/**
   Execution sequence and Analysis :
   The order :
    * 123
   analysis :
     Under normal circumstances , async  Medium  await  The order is a  Promise  object , Returns the result of the object 
     But if not  Promise  Object words , The corresponding value will be returned directly , amount to  Promise.resolve();
*/

15.6 Topic 6

Return directory
async function async1() {
  console.log('async1 start');
  await new Promise((resolve) => {
    console.log('promise1');
  })
  console.log('async1 success');
  return 'async1 end';
}

console.log('script start');

async1().then((res) => {
  console.log('res: ', res);
})

console.log('script end');

/**
   Execution sequence and Analysis :
   The order :
    * 'script start'
    * 'async1 start'
    * 'promise1'
    * 'script end'
   analysis :
    1.  Special questions 
    2.  stay  await  hinder  Promise  There is no return value , therefore  await  Will be waiting 
    3.  In this case ,async1 success  None of the following will be implemented 
   reflection :
     If in  'promise1'  Add a line after  resolve('123');  What will happen ?
*/

15.7 Topic 7

Return directory
async function async1() {
  console.log('async1 start');
  await new Promise((resolve) => {
    console.log('promise1');
    resolve('promise resolve');
  })
  console.log('async1 success');
  return 'async1 end';
}

console.log('script start');

async1().then((res) => {
  console.log('res: ', res);
})

new Promise((resolve) => {
  console.log('promsie2');
  setTimeout(() => {
      console.log('timer');
  }, 0);
})

/**
   Execution sequence and Analysis :
   The order :
    * 'script start'
    * 'async1 start'
    * 'promise1'
    * 'promsie2'
    * 'async1 success'
    * 'res: async1 end'
    * 'timer'
   analysis :
    1.  Following the analysis of the previous question ,Promise  must  resolve  了 ,await  Later code will continue to execute 
    2.  Take the whole thing first  script  Macro task , Output  'script start'
    3.  meet  async1()  Implementation , Go inside and have a look 
    4.  Output  'async1 start'
    5.  meet  await new Prmise
    6.  Output  'promise1'
    7.  notice  resolve, change  Promise  state , inform  await  There are waiting objects , Throw the rest of the content into the micro task  1
    8.  Go ahead and do the following  new Promsie
    9.  Output  'promsie2'
    10.  take  setTimeout  Throw in the macro task  1
    11.  Now there's a micro task  1  And a macro task  1
    12.  Go ahead with micro tasks  1
    13.  Output  'async1 success'
    14.  meet  return, Tell me to add a micro task after  2
    15.  Continue to perform micro tasks  2, Output  'res: async1 end'
    16.  There are no other micro tasks , Macro output task queue , Output  'timer1'
*/

15.8 Topic 8

Return directory
async function async1() {
  console.log('async1 start');
  await async2();
  console.log('async1 end');
}

async function async2() {
  console.log('async2');
}

console.log('script start');

setTimeout(() => {
  console.log('settimeout');
}, 0);

async1();

new Promise((resolve) => {
  console.log('promise1');
  resolve();
}).then((res) => {
  console.log('promise2');
})

console.log('script end');

/**
   Execution sequence and Analysis :
   The order :
    * 'script start'
    * 'async1 start'
    * 'async2'
    * 'promise1'
    * 'script end'
    * 'promise2'
    * 'async1 end'
    * 'settimeout'
   analysis :
     There's no need to explain here , Similar to the title above 
*/

15.9 Topic nine

Return directory
async function async1() {
  console.log('async1 start');
  await async2();
  console.log('async1 end');
}

async function async2() {
  console.log('async2');
}

console.log('script start');

setTimeout(() => {
  console.log('settimeout');
}, 0);

async1();

new Promise((resolve) => {
  console.log('promise1');
  resolve();
}).then((res) => {
  console.log('promise2');
})

console.log('script end');

/**
   Execution sequence and Analysis :
   The order :
    * 'script start'
    * 'async1 start'
    * 'async2'
    * 'promise1'
    * 'script end'
    * 'async1 end'
    * 'promise2'
    * 'settimeout'
   Be careful :
     The output here is  'async1 end'  and  'promise2', stay  Node v10.16.0  It's the reverse 
   analysis :
     There's no need to explain here , Similar to the title above 
*/

15.10 Topic ten

Return directory
async function testSomething() {
  console.log('test something');
  return 'test something';
}

async function testAsync() {
  console.log('test async');
  return Promise.resolve('hello test async');
}

async function test() {
  console.log('test start');

  const v1 = await testSomething();
  console.log('v1: ', v1);

  const v2 = await testAsync();
  console.log('v2: ', v2);

  console.log(v1, v2);
}

test();

const promise = new Promise((resolve) => {
  console.log('promise start');
  resolve('promise');
})

promise.then((val) => {
  console.log(val);
})

console.log('test end');

/**
   Execution sequence and Analysis :
   The order :
    * 'test start'
    * 'test something'
    * 'promise start'
    * 'test end'
    * 'v1: test something'
    * 'test async'
    * 'promise'
    * 'v2: hello test async'
    * 'test something' 'hello test async'
   Be careful :
     The output here is  Node v10.16.0  Is different 
   analysis :
     There's no need to explain here , Similar to the title above 
*/

15.11 Topic eleven

Return directory

Get started async Deal with wrong questions .

async function async1() {
  await async2();
  console.log('async1');
  return 'async1 success';
}

async function async2() {
  return new Promise((resolve, reject) => {
    console.log('async2');
    reject('error');
  })
}

async1().then((res) => {
  console.log('res: ', res);
})

/**
   Execution sequence and Analysis :
   The order :
    * 'async2'
    * Promise {<rejected>: "error"}
   analysis :
     If in  async  Error thrown in function , The error result is terminated , Will not continue down .throw new Error  So it is with .
*/

sixteen Comprehensive questions

Return directory

16.1 Topic 1

Return directory
const first = () => (new Promise((resolve1, reject1) => {
  console.log(3);
  
  const p = new Promise((resolve2, reject2) => {
    console.log(7);
    
    setTimeout(() => {
      console.log(5);
      resolve1(6);
      console.log(p);
    }, 0);

    resolve2(1);
  });

  resolve1(2);

  p.then((res1) => {
    console.log('res1: ', res1);
  });
}));

first().then((res2) => {
  console.log('res2: ', res2);
});

console.log(4);

/**
   Execution order :
    * 3
    * 7
    * 4
    * res: 1
    * res: 2
    * 5
    * Promise{ <resolve> 1 }
*/

16.2 Topic two

Return directory
const async1 = async() => {
  console.log('async1');
  
  setTimeout(() => {
    console.log('timer1');
  }, 2000);

  await new Promise((resolve) => {
    console.log('promise1');
  })

  console.log('async1 end');
  return 'async1 success';
};

console.log('script start');

async1().then((res1) => {
  console.log('res1: ', res1);
})

console.log('script end');

Promise
.resolve(1)
.then(2)
.then(Promise.resolve(3))
.catch(4)
.then((res2) => {
  console.log('res2: ', res2);
})

setTimeout(() => {
  console.log('timer2');
}, 1000);

/**
   Execution order :
    * 'script start'
    * 'async1'
    * 'promise1'
    * 'script end'
    * 'res2: 1'
    * 'timer2'
    * 'timer1'
*/

16.3 Topic three

Return directory
const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve('resolve3');
    console.log('timer1');
  }, 0);
  resolve('resolve1');
  resolve('resolve2');
}).then((res) => {
  console.log(res);
  setTimeout(() => {
    console.log(p1);
  }, 1000);
}).finally((res) => {
  console.log('finally: ', res);
})

/**
   Execution order :
    * 'resolve1'
    * 'finally: undefined'
    * 'timer1'
    * 'Promise { <resolved> undefined }'
*/

seventeen Big factory

Return directory

17.1 Use Promise Output every second 1、2、3

Return directory
const oneToThree = () => {
  const arr = [1, 2, 3];
  arr.reduce((prev, next) => {
    return prev.then(() => {
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log(next);
          resolve();
        }, 1000);
      })
    });
  }, Promise.resolve())
};

console.log(oneToThree());

rewrite forEach:

/**
 *  Implementation function  forEach(arr, cb), send  cb  Deal with one by one  arr  The elements in 
 *  A process can be synchronous , It can also be asynchronous 
 *  The current element must be processed before the next one can be processed .
 *  Tips :cb  If the function is executed asynchronously , Will return a  Promise
 */
const liangEach = (arr, cb) => {
  arr.reduce((prev, next) => {
    return prev.then((res1) => {
      return cb(next);
    });
  }, Promise.resolve())
};

const arr = [1, 2, 5];

liangEach(arr, (n) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(n);
      resolve();
    }, 1000);
  })
})

If there is async/await Realization :

/**
 *  Implementation function  forEach(arr, cb), send  cb  Deal with one by one  arr  The elements in 
 *  A process can be synchronous , It can also be asynchronous 
 *  The current element must be processed before the next one can be processed .
 *  Tips :cb  If the function is executed asynchronously , Will return a  Promise
 */
async function liangEach(arr, cb) {
  for (let i = 0; i < arr.length; i++) {
    await cb(arr[i]);
  }
};

const arr = [1, 2, 5];

liangEach(arr, (n) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(n);
      resolve();
    }, 1000);
  })
});

17.2 Use Promise The traffic lights turn on repeatedly

Return directory

A red light 3 Second light once , Yellow light 2 Second light once , A green light 1 Second light once , use Promise Realization 3 The lights turn on and on again and again .

Known functions :

function red() {
  console.log('red');
}
function yellow() {
  console.log('yellow');
}
function green() {
  console.log('green');
}

answer :

function red() {
  console.log('red');
}
function yellow() {
  console.log('yellow');
}
function green() {
  console.log('green');
}

const light = (timer, cb) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      cb();
      resolve();
    }, timer);
  })
}

const step = () => {
  Promise.resolve().then(() => {
    return light(3000, red);
  }).then(() => {
    return light(2000, yellow);
  }).then(() => {
    return light(1000, green);
  }).then(() => {
    return step();
  })
};

step();

17.3 Realization mergePromise function

Return directory

Realization mergePromise function , The array passed in is executed in sequence , And put the returned values in the array data in .

for example :

const time = (timer) => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve()
    }, timer)
  })
}
const ajax1 = () => time(2000).then(() => {
  console.log(1);
  return 1
})
const ajax2 = () => time(1000).then(() => {
  console.log(2);
  return 2
})
const ajax3 = () => time(1000).then(() => {
  console.log(3);
  return 3
})

function mergePromise () {
  //  Write the code here 
}

mergePromise([ajax1, ajax2, ajax3]).then(data => {
  console.log("done");
  console.log(data); // data  by  [1, 2, 3]
});

//  Ask to output separately 
// 1
// 2
// 3
// done
// [1, 2, 3]

answer :

const time = (timer) => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve()
    }, timer)
  })
}
const ajax1 = () => time(2000).then(() => {
  console.log(1);
  return 1
})
const ajax2 = () => time(1000).then(() => {
  console.log(2);
  return 2
})
const ajax3 = () => time(1000).then(() => {
  console.log(3);
  return 3
})

function mergePromise (ajaxList) {
  const data = [];
  let promise = Promise.resolve();

  ajaxList.forEach((ajax) => {
    promise = promise.then(() => {
      return ajax();
    }).then((resolve) => {
      data.push(resolve);
      return data;
    })
  })

  return promise;
}

mergePromise([ajax1, ajax2, ajax3]).then(data => {
  console.log("done");
  console.log(data); // data  by  [1, 2, 3]
});

//  Ask to output separately 
// 1
// 2
// 3
// done
// [1, 2, 3]

17.4 according to PromiseA+ Realize one of your own Promise

Return directory

stay jsliang Handwritten source code series has a detailed analysis .

17.5 Encapsulate a method to load images asynchronously

Return directory
function loadImg(url) {
  // ... Implementation code 
}

answer :

function loadImg(url) {
  return new Promise((resolve, reject) => {
    const image = new Image();
    image.onload = () => {
      console.log(' Image loading complete ');
      resolve(image);
    }
    image.onerror = () => {
      reject(new Error(' Loading failed ' + url));
    }
    image.src = url;
  })
}

17.6 Limit the number of concurrent asynchronous operations and complete them as quickly as possible

Return directory

List of known pictures :

var urls = [
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting1.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting2.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting3.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting4.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting5.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn6.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn7.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn8.png",
];

Known functions :

function loadImg(url) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = function() {
      console.log(" A picture is loaded ");
      resolve(img);
    };
    img.onerror = function() {
        reject(new Error('Could not load image at' + url));
    };
    img.src = url;
  });
};

function limitLoad(urls, handler, limit) {
  // ... Implementation code 
}

Please download at the same time the link proficiency does not exceed 3 In the case of , Finish as soon as possible .

const urls = [
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting1.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting2.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting3.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting4.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting5.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn6.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn7.png",
  "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn8.png",
];
function loadImg(url) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = function() {
      console.log(" A picture is loaded ");
      resolve(img);
    };
    img.onerror = function() {
        reject(new Error('Could not load image at' + url));
    };
    img.src = url;
  });
}

function limitLoad(urls, handler, limit) {
  let sequence = [].concat(urls); //  Copy urls
  //  This step is to initialize  promises  This " Containers "
  let promises = sequence.splice(0, limit).map((url, index) => {
    return handler(url).then(() => {
      //  The subscript is returned to know which item in the array is completed first 
      return index;
    });
  });
  //  Note that the entire variable procedure is returned here , So you get a Promise, You can chain call it outside 
  return sequence
    .reduce((pCollect, url) => {
      return pCollect
        .then(() => {
          return Promise.race(promises); //  Returns the completed subscript 
        })
        .then((fastestIndex) => {
          //  Get the completed subscript 
          //  take " Containers " The replacement that has been completed in 
          promises[fastestIndex] = handler(url).then(() => {
            return fastestIndex; //  To continue to return the subscript to , So that the next variable 
          });
        })
        .catch((err) => {
          console.error(err);
        });
    }, Promise.resolve()) //  Initialize incoming 
    .then(() => {
      //  The last three use .all To call 
      return Promise.all(promises);
    });
}
limitLoad(urls, loadImg, 3)
  .then((res) => {
    console.log(" All the pictures are loaded ");
    console.log(res);
  })
  .catch((err) => {
    console.error(err);
  });

17.7 JS Implement asynchronous scheduler

Return directory

Review the question and complete the following code :

/**
 *  subject :JS  Implement asynchronous scheduler 
 *  requirement :
 *  JS  Implement an asynchronous scheduler with concurrency constraints  Scheduler, The maximum number of tasks guaranteed to run simultaneously is  2  individual 
 *   Perfect the following code  Scheduler  class , Make the program output correctly 
 */

class Scheduler {
  add(promiseCreator) {
    // ...
  }
  // ...
}

const timeout = (time) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
};
const scheduler = new Scheduler();
const addTack = (time, order) => {
  return scheduler
    .add(() => timeout(time))
    .then(() => console.log(order));
};
addTack(1000, '1');
addTack(500, '2');
addTack(300, '3');
addTack(400, '4');

//  Output :2 3 1 4
//  In limine ,1、2  Two tasks enter the queue 
// 500ms  when , complete  2, Output  2, Mission  3  Enter the team 
// 800ms  when , complete  3, Output  3, Mission  4  Enter the team 
// 1000ms  when , complete  1, Output  1, There's no one in the team 
// 1200ms  when , complete  4, Output  4, There's no one in the team 
//  Team entry complete , Output  2 3 1 4

Realization way (async/await):

/**
 *  subject :JS  Implement asynchronous scheduler 
 *  requirement :
 *  JS  Implement an asynchronous scheduler with concurrency constraints  Scheduler, The maximum number of tasks guaranteed to run simultaneously is  2  individual 
 *   Perfect the following code  Scheduler  class , Make the program output correctly 
 */

class Scheduler {
  constructor(maxNum) {
    this.taskList = [];
    this.count = 0;
    this.maxNum = maxNum; //  Maximum number of concurrent 
  }
  async add(promiseCreator) {
    //  If the current concurrency exceeds the maximum concurrency , Then enter the task queue and wait 
    if (this.count >= this.maxNum) {
      await new Promise((resolve) => {
        this.taskList.push(resolve);
      })
    }

    //  frequency  + 1( If the previous one is not finished , Then keep adding )
    this.count++;

    //  Wait for the content to be executed 
    const result = await promiseCreator();

    //  frequency  - 1
    this.count--;

    //  Get the team out of the team first 
    if (this.taskList.length) {
      this.taskList.shift()();
    }

    //  call chaining  , Return the result value 
    return result;
  }
}

const timeout = (time) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
};

const scheduler = new Scheduler(2);
const addTack = (time, order) => {
  return scheduler
    .add(() => timeout(time))
    .then(() => console.log(order));
};
addTack(1000, '1');
addTack(500, '2');
addTack(300, '3');
addTack(400, '4');

//  Output :2 3 1 4
//  In limine ,1、2  Two tasks enter the queue 
// 500ms  when , complete  2, Output  2, Mission  3  Enter the team 
// 800ms  when , complete  3, Output  3, Mission  4  Enter the team 
// 1000ms  when , complete  1, Output  1, There's no one in the team 
// 1200ms  when , complete  4, Output  4, There's no one in the team 
//  Team entry complete , Output  2 3 1 4

eighteen summary

Return directory

Write here , Finally, I've finished all the content .

First , Most of the titles of this article , Taken from the LinDaiDai_ Lin is stupefied The article , Thank you very much for his article , I spent it. 8 hours , Combine these topics with browsers and Node The print of the , Finally, we have a rough idea of this related content .

meanwhile , During the period of jobless vagrant , Appreciate the dull encouragement , Be confident in your job search .

then , This article is probably Promise It's a letter of persuasion !

Because according to the estimates I compiled and collated , It takes about a week to read and master !

however , If you really finish watching , So congratulations :Promise You have already got through the two channels of Ren Du .

Last , If your partner thinks the article is good , All kinds of encouragement are welcome ( give the thumbs-up 、Star……), Contact information can be personal Github home page , If you have any questions, please try to chat in private , After all, sometimes I really feel that time is not enough :

that , I'll see you later !


jsliang The document library of is made up of Liang Junrong use Knowledge sharing A signature - Noncommercial use - Share in the same way 4.0 The international license agreement Licensing .<br/> be based on https://github.com/LiangJunrong/document-library Creation of works on .<br/> Use rights other than those authorized by this license agreement can be obtained from https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ To obtain .

版权声明
本文为[jsliang]所创,转载请带上原文链接,感谢