JS是单线程的:大部分代码都是同步的,但是也有少部分代码是异步编程的

  1. 异步宏任务
    1. 定时器
    2. ajax:一般都是异步的
    3. 事件绑定
  2. 异步微任务

    1. promise
    2. async await
    3. generator
    4. requestAnimationFrame

      Promise

  3. 是什么:异步编程解决方案,ES6内置类,承诺模式

  4. 干什么:
    1. 有了 Promise 对象,就可以将异步操作以同步操作的流程(链式调用)表达出来,避免了层层嵌套的回调函数(回调地狱)。
    2. 此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
  5. _let p = new Promise([executor]);_
  6. [executor]:可执行函数
    1. new Promise的时候,在Promise内部会立即把[executor]函数执行(同步的)
    2. 函数中一般用来管理一个异步编程代码(不管控异步编程也是可以的)
    3. 同时给[executor]函数传递两个值「函数类型」:resolve / reject
  7. p 是Promise类的一个实例, 可以在里面chrome调试器里直接看到的东西,可以直接学习

    1. 内置私有属性 外面有两个[[ ]] 包起来的
      1. [[PromiseState]] 实例状态:
        1. pending [准备状态]
        2. fulfilled/resolved [成功态] rejected [失败态]
      2. [[PromiseResult]] 实例的值
    2. 公共属性方法 Promise.prototype
      1. then
      2. catch
      3. finally
      4. Symbol(Symbol.toStringTag): “Promise” => 通过 **Object.prototype.toString.call(p)** => “[object Promise]”

        promise使用

  8. 在[executor]执行 resolve / reject 都是为了改变 promise实例 状态和值「结果」

  9. 一但状态被改变成 fulfilled / rejected不能再改为其他的状态

    1. resolve(‘OK’);
      1. [[PromiseState]]:fulfilled [[PromiseResult]]:'OK'
    2. reject(‘NO’);
      1. [[PromiseState]]:rejected [[PromiseResult]]:'NO'
  10. 如果[executor]函数执行执行出错,则

    1. [[PromiseState]]:rejected [[PromiseResult]]:报错原因
    2. Promise内部做了异常信息捕获「try/catch」
  11. 实例状态的改变,可以控制,执行then方法时,存放的两个方法中的某一个方法执行

    1. p.then(onfulfilledCallback, onrejectedCallback)
    2. 状态成功执行的是:onfulfilledCallback
    3. 状态失败执行的是:onrejectedCallback ```javascript let p1 = new Promise((resolve, reject) => { reject(‘NO’); });

p1.then(result => { console.log(‘成功—>’, result); }, reason => { console.log(‘失败—>’, reason); });

p1.then(result => { console.log(‘成功—>’, result); }, reason => { console.log(‘失败—>’, reason); });

  1. <a name="wDVvR"></a>
  2. ## 同步异步?
  3. 1. 执行`**p.then(onfulfilledCallback,onrejectedCallback)**`
  4. 1. 首先把传递进来的`onfulfilledCallback`和`onrejectedCallback`存储起来「存储在一个容器中:因为可以基于then给其存放好多个回调函数」
  5. 1. 其次再去**验证当前实例(p)的状态**
  6. 1. 如果实例状态是 `pending`,则不做任何的处理
  7. 1. 如果已经变为`fulfilled`/`rejected`,则会通知对应的回调函数执行
  8. 1. 但是**不是立即执行**,而是把其放置在EventQueue中的**微任务队列**中
  9. **promise本身不是异步的**,**是用来管理异步的**<br />**但是then方法是异步的「微任务」**
  10. 例一:
  11. ```javascript
  12. let p = new Promise((resolve, reject) => {
  13. console.log(1);
  14. resolve('OK'); //=>同步修改其状态和结果
  15. console.log(2);
  16. });
  17. console.log(p); //此时状态已经修改为成功...
  18. // 不是立即执行,而是把其放置在EventQueue中的微任务队列中
  19. p.then(result => {
  20. console.log('成功-->', result);
  21. });
  22. console.log(3);
  23. // 同步执行完了,再在微任务队列里执行里面的东西

Promise - 图1

例二:

刚开始打印:
Promise - 图2
1000ms之后:
Promise - 图3

  1. resolve

    1. resolve值和状态的改变同步的
    2. 但是通知then方法存放的onfulfilledCallback执行则是异步的
    3. 我们也可以说,promise的异步也来源于resolve和reject
      1. let p = new Promise((resolve, reject) => {
      2. console.log(1);
      3. setTimeout(() => {
      4. resolve('OK');
      5. // + 改变实例的状态和值「同步」
      6. // + 通知之前基于then存放的onfulfilledCallback执行「异步的微任务:也是把执行方法的事情放置在EventQueue中的微任务队列中」
      7. console.log(p);
      8. console.log(4);
      9. }, 1000); //=>存储了一个异步的宏任务
      10. console.log(2);
      11. });
      12. console.log(p);
      13. // 此时接受onfulfilledCallback的时候,状态还是pending,此时只把方法存储起来
      14. p.then(result => {
      15. console.log('成功-->', result);
      16. });
      17. console.log(3);
      18. // 等1000ms后,执行定时器中的函数「把异步宏任务拿出来执行」

      then的链式调用

  2. 执行then方法会返回一个全新的promise实例p2

  3. p2的状态和值是咋改变的?
  4. 不论执行的是基于p1.then存放的onfulfilledCallback/onrejectedCallback两个方法中的哪一个
    1. 只要方法执行不报错
      1. 如果方法中返回一个全新的Promise实例,则“全新的Promise实例”的成功和失败决定p2的成功和失败
      2. 如果不是返回promise呢?则 [[``PromiseState``]]:``fulfiled`` [[``PromiseResult``]]:返回值
    2. 如果方法执行报错:p2的 [[PromiseState]]:rejected [[PromiseResult]]:报错原因

promise实例 状态和值目前改变方法:

  1. 本身:
    1. resolve / reject 的执行
    2. resolve执行是否报错
  2. then方法相关
    1. then 方法中返回的promise实例情况
      1. Promise.reject(10);
      2. Promise.resolve(10);
    2. 不返回promise
      1. [[``PromiseState``]]:``fulfiled [[``PromiseResult``]]:返回值
    3. then 两个方法执行是否报错

注意!!p2的状态和p1成功失败没关系:就算p1失败了,但里面没报错,也没返回reject的promise,p2就不会是失败的
Promise - 图4

  1. let p1 = new Promise((resolve, reject) => {
  2. resolve('OK');
  3. // reject('NO');
  4. });
  5. let p2 = p1.then(result => {
  6. console.log('P1成功-->', result);
  7. return Promise.reject(10);
  8. }, reason => {
  9. console.log('P1失败-->', reason);
  10. });
  11. let p3 = p2.then(result => {
  12. console.log('P2成功-->', result);
  13. }, reason => {
  14. console.log('P2失败-->', reason);
  15. return Promise.resolve(10);
  16. });
  17. p3.then(result => {
  18. console.log('P3成功-->', result);
  19. }, reason => {
  20. console.log('P3失败-->', reason);
  21. return Promise.resolve(10);
  22. });
  23. console.log(1);
  1. 顺延机制
    1. 如果onfulfilledCallback/onrejectedCallback不传递,则状态和结果都会“顺延/穿透”到下一个同等状态应该执行的回调函数上「内部其实是自己补充了一些实现效果的默认函数」
      1. result=> result
      2. reason=> Promise.reject(reason) ```javascript

new Promise((resolve, reject) => { // resolve(‘OK’); reject(‘NO’); }).then(null, reason=>{ // 这里传null, console.log(‘失败—>’,reason); }).then(result => { console.log(‘成功—>’, result); }, reason => { console.log(‘失败—>’, reason); }).then(result => { console.log(‘成功—>’, result); }, reason => { console.log(‘失败—>’, reason); });

  1. catch只处理状态为失败下做的事情
  2. ```javascript
  3. Promise.prototype.catch = function (onrejectedCallback) {
  4. return this.then(null, onrejectedCallback);
  5. };

then只放成功,catch放失败

后盾人的一道题

  1. async function hd(num) {
  2. let res = await Promise.resolve().then(() => {
  3. let count = 0;
  4. debugger
  5. for (let i = 0; i < num; i++) {
  6. count += num--
  7. }
  8. return count
  9. })
  10. console.log(res);
  11. }
  12. hd(3125651) //这个函数是为了出来大量计算 但又不想影响主线程后面的输出 所以用了.then异步的微任务特性
  13. console.log('后盾人');