1. Basic concepts

  • ES6 has a new built-in class, Promise, that handles asynchronous programming effectively

1.1 Start with a requirement

  • AJAX serial requirements: first get data from the server side based on/API /1, get other data as a parameter based on/API /2, and finally get data based on 2 based on/API /3
$.ajax({
  url: '/api/1'.method: 'GET'.dataType: 'json'.success: function(result) {
    console.log(result)
    $.ajax({
      url: '/api/2'.method: 'GET'.dataType: 'json'.success: function(result) {
        console.log(result)
      }
    })
  }
})
Copy the code
  • Promise manages asynchronous programming
const api1 = () = > {
  return new Promise(resolve= > {
    $.ajax({
      url: '/api/1'.method: 'GET'.dataType: 'json'.success(result) {
        resolve(result)
      }
    })
  })
}

api1().then(result= > {
  console.log('First request successful', result)
  return api2();
}).then(result= > {
  console.log('Second request successful', result)
  return api3();
}).then(result= > {
  console.log('Third request successful', result)
});
Copy the code
  • A simpler way to write it based on Promise
(async function() {
  let result = await api1();
  console.log('First request successful', result)
  result = await api2();
  console.log('Second request successful', result)
  result = await api3();
  console.log('Third request successful', result)
})();
Copy the code

1.2 Asynchronous programming in JS

  • An ajax request
  • event
  • The timer
  • Promise/async/await
  • requestAnimationFrame
setTimeout(() = > {
  console.log(1);
}, 1000);
console.log(2);
// Print 1 after 2
Copy the code

2. I Promise

2.1 shall be the executor

  • When new, one must be passedexecutorFunction in
let p1 = new Promise(a);// Promise resolver undefined is not a function
Copy the code

2.2 New Promise

2.2.1 will execute the passed executor function immediately
  • Used in executor functions to manage an asynchronous operation
    • Other synchronous code that does not write asynchronous operations and does not change state (reslove, reject) executes synchronously
    • When resolve/ REJECT is executed, the status information is immediately changed, but method execution is not immediately notified (with asynchronous effects)
    • Reslove changes state synchronously, and then performs callbacks asynchronously
  • The executor function takes two arguments, resolve and reject, which are both functions
2.2.2 An instance of the new Promise class p1, console.log(p1)
  • Each promise instance has [[PromiseState]] and [[PromiseResult]]
  • [[PromiseState]]Promise: Pending/regrettable /resolved/Rejected
  • [[PromiseResult]]Promise value: default undefined, usually storing the result of success or the reason for failure
  • P1.__proto__ points to promise.prorotype (then/catch/finallyThree ways)
2.2.3 Status Change rules
  • If resolve is executed, the state of the control instance becomes successful and the value passed is the result [[PromiseResult]].
  • Reject, controls the instance state to fail, passing the result [[PromiseResult]]
  • Once the state changes from pending, all subsequent operations are invalid (eg: resolve, reject, invalid).
  • [[PromiseResult]] indicates the rejected state. [[PromiseResult]] indicates the rejected state
  • The state pending becomes Resolved by executing resolve() when the asynchronous code succeeds
2.2.4 Code execution sequence 1
    1. “New Promise” to create a Promise instance
    1. Execute executor and set an asynchronous timer
    1. Execute the two methods injected with p1.then, and the injected methods are saved (synchronized)
    1. Waiting for 1000 ms
    1. Execute the timer callback to change the state and value of the promise (resolve is asynchronous)
    1. Execute one based on the two methods injected earlier with THEN, combined with state
let p1 = new Promise(function(resolve, reject) {
  setTimeout(() = > 
    reslove('ok')},1000)
})
p1.then(result= > {
  // this function will be executed gradually, result->[[PromiseResult]]
}, reason= > {
  // This function is run when p1 is rejected, reason->[[PromiseResult]]
})
Copy the code
2.2.5 Code execution sequence 2
    1. Output 1
    1. Reslove is an asynchronous operation that is performed on a queue of waiting tasks. Reslove is an asynchronous operation that is performed on a queue of waiting tasks.New Promises are synchronized.Reslove notification injection execution is asynchronousAt this point, P1 has been successfully stored temporarily
    1. The output of 2
    1. Start the injection method, save
    1. The output of 3
    1. Asynchronous queue, perform injection. Then execute
let p1 = new Promise(function(resolve, reject) {
  console.log(1)
  resolve('OK')
  console.log(2)
})
p1.then(result= > {
  console.log('success - >', result)
}, reason= > {
  console.log('failure - >', reason)
})
console.log(3)
Copy the code
2.2.6 Code execution sequence 3
  • Resolve is asynchronous, is not processed immediately and is placed on a wait queue

  • After 1s, change the state and value and store it to the asynchronous queue, at which point the method has been injected

  • Synchronization starts with 1

  • Execute then, printing 2

let p1 = new Promise(resolve= > {
  setTimeout(() = > {
    resolve('OK')
    console.log(1)},1000)
})
p1.then(result= > {
  console.log(2)})Copy the code

3. I Promise more

let p1 = new Promise(resolve= > {
  resolve('OK')})// The top can be shortened to the bottom
// Create a successful promise instance
// let p1 = Promise.resolve('OK')

let p2 = p1.then(result= > {
  console.log('success - >', result)
}, reason= > {
  console.log('failure - >', reason)
})

// P2 is a brand new promise instance

p2.then(result= > {
  console.log('success - >', result)
}, reason= > {
  console.log('failure - >', reason)
})
Copy the code
  • The.then implementation returns a brand new promise instance

3.1 Analysis of state and value of promise instance

3.1.1 Example of New Promise (P1)
  • The resolve/reject execution controls its state as well as its outcome
  • The executor function failed to execute, causing the status to fail
3.1.2 New Promise instance returned by executing. Then (p2)
  • This will be a big pity. No matter which method is implemented, as long as no error is reported during the implementation, the state of the new instance is fulfilled, which is the promise value of the new instance P2, which is returned by the method
  • If the method executes and returns a new promise instance, then the final state of that instance determines the success and failure of the.then return
let p1 = new Promise(resolve= > {
  resolve('OK')})let p2 = p1.then(result= > {
  console.log('success - >', result)
  return 10
}, reason= > {
  console.log('failure - >', reason)
})
p2.then(result= > {
  console.log('success - >', result)
}, reason= > {
  console.log('failure - >', reason)
})
// p1 is successful, output is successful, ok
// p2 is the return success of p1, output success, 10
Copy the code
let p1 = new Promise((resolve, reject) = > {
  reject('No')})let p2 = p1.then(result= > {
  console.log('success - >', result)
  return 10
}, reason= > {
  console.log('failure - >', reason)
  return 20
})
p2.then(result= > {
  console.log('success - >', result)
}, reason= > {
  console.log('failure - >', reason)
})
// p1 failed, output failed, No
// p2 is the return success of p1, output success, 20
Copy the code
let p1 = Promise.resolve('OK')
let p2 = p1.then(result= > {
  console.log('success - >', result)
  return Promise.reject('No')},reason= > {
  console.log('failure - >', reason)
  return 20
})
p2.then(result= > {
  console.log('success - >', result)
}, reason= > {
  console.log('failure - >', reason)
})
// p1 is successful, output is successful, ok
// p2, output failed, No
Copy the code
3.1.3 postpone
  • For failed promise instances, if no method is written to handle the result, an exception is thrown, but the rest of the code is not prevented from executing
  • If it fails,.then is the failure state of the last one
  • When a method is injected into a. Then, if one of the methods is not passed, it is deferred to the next then function that has the same state and needs to be executed
Promise.reject('No').then(result= > {
  console.log('success', result)
  return 10;
}).then(null.reason= > {
  console.log('failure', reason)
})
Copy the code
Promise.resolve('ok').then(null.reason= > {
   console.log('failure', reason)
}).then(result= > {
  console.log('success', result)
})
Copy the code
  • Catch the last error usedcatchInstead of
Promise.resolve('ok').then(null.reason= > {
   console.log('failure', reason)
}).then(result= > {
  console.log('success', result)
}).then(result= > {
  console.log('success', result)
}).catch(reason= > {
 console.log('failure', reason)
})
Copy the code

3.2 Promise. All & Promise. Race

  • Promise.all Waits for all Promise instances to succeed before the whole state returns, one failure, all failure
  • Promise.race looks at multiple instances to see which one finishes first, and the state that finishes first, whether it succeeds or fails, is the overall state
const api1 = () = > {}
const api2 = () = > {}
const api3 = () = > {}
const fn = () = > {
  return new Promise(resolve= > {
    setTimeout(() = > {
      resolve(100)},1000)})}const AA = Promise.reaolve('AA')

let p  = Promise.all([api1(), api2(), api3(), AA, fn(), 10]);
p.then(results = > {
  // The array of each result is stored in the order previously set, regardless of who returns first
  console.log('All results', results)
}).catch(reason= > {
  // As long as one failure, the whole failure, go here, immediately end processing, who failed, record the failure reason
  console.log('err->', reason)
})
Copy the code