espera, asíncrono, bucle de eventos (macrotarea, secuencia de ejecución de cola de microtareas)

1 asíncrono, espera

2 Proceso del navegador, hilo

3 Macro tarea, cola de micro tarea

4 Análisis de preguntas de la entrevista de promesa

5 lanzar, intentar, atrapar, finalmente

Función asincrónica: cómo escribir una función asincrónica

 // 普通函数
    // function foo() {}
    // const bar = function() {}
    // const baz = () => {}

    // 生成器函数
    // function* foo() {}

    // 异步函数
    async function foo() {
      console.log("foo function1")
      console.log("foo function2")
      console.log("foo function3")
    }
    foo()

    // const bar = async function() {}
    // const baz = async () => {}
    // class Person {
    //   async running() {}
    // }

función asíncrona - valor de retorno de la función asíncrona

// 返回值的区别
    // 1.普通函数
    // function foo1() {
    //   return 123
    // }
    // foo1()

    // 2.异步函数
    async function foo2() {
      // 1.返回一个普通的值
      // -> Promise.resolve(321)
      return ["abc", "cba", "nba"]

      // 2.返回一个Promise
      // return new Promise((resolve, reject) => {
      //   setTimeout(() => {
      //     resolve("aaa")
      //   }, 3000)
      // })

      // 3.返回一个thenable对象
      // return {
      //   then: function(resolve, reject) {
      //     resolve("bbb")
      //   }
      // }
    }

    foo2().then(res => {
      console.log("res:", res)
    })

Funciones asíncronas: excepciones para funciones asíncronas

Si hay errores o excepciones en el código asíncrono, no afectará el código posterior, pero los resultados se pasarán en el rechazo de la promesa.

 // "abc".filter()

    // 什么情况下异步函数的结果是rejected

    // 如果异步函数中有抛出异常(产生了错误), 这个异常不会被立即浏览器处理
    // 进行如下处理: Promise.reject(error)
    async function foo() {
      console.log("---------1")
      console.log("---------2")
      // "abc".filter()
      throw new Error("coderwhy async function error")
      console.log("---------3")

      // return new Promise((resolve, reject) => {
      //   reject("err rejected")
      // })

      return 123
    }

    // promise -> pending -> fulfilled/rejected
    foo().then(res => {
      console.log("res:", res)
    }).catch(err => {
      console.log("coderwhy err:", err)
      console.log("继续执行其他的逻辑代码")
    })

Función asincrónica: espera el uso de palabras clave

Await es inútil si se usa simplemente en variables ordinarias y funciones ordinarias. Se usa junto con la promesa. Su función es similar a la de rendimiento. Es esperar hasta que la promesa regrese antes de recibir el resultado y luego ejecutar el código en el próximas líneas de espera (interrumpirá la ejecución del código).

// 1.普通函数
    // function foo1() {
    //   await 123
    // }
    // foo1()


    // 2.await关键字
    // await条件: 必须在异步函数中使用
    function bar() {
      console.log("bar function")
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(123)
        }, 100000)
      })
    }

    async function foo() {
      console.log("-------")
      // await后续返回一个Promise, 那么会等待Promise有结果之后, 才会继续执行后续的代码
      const res1 = await bar()
      console.log("await后面的代码:", res1)
      const res2 = await bar()
      console.log("await后面的代码:", res2)

      console.log("+++++++")
    }

    foo()

La función asincrónica en espera maneja solicitudes asincrónicas

Cuando la promesa devuelve un rechazo, se puede utilizar catch para detectar excepciones y errores. O escriba try catch en getdata.

 function requestData(url) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(url)
          // reject("error message")
        }, 2000);
      })
    }

    async function getData() {
      const res1 = await requestData("why")
      console.log("res1:", res1)

      const res2 = await requestData(res1 + "kobe")
      console.log("res2:", res2)
    }

    getData().catch(err => {
      console.log("err:", err)
    })

Función asincrónica: combinación de espera y asíncrona

Las funciones ordinarias devuelven promesas, pero las funciones creadas con la palabra clave asincrónica async también pueden usar await al llamar.

  // 1.定义一些其他的异步函数
    function requestData(url) {
      console.log("request data")
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(url)
        }, 3000)
      })
    }

    async function test() {
      console.log("test function")
      return "test"
    }

    async function bar() {
      console.log("bar function")

      return new Promise((resolve) => {
        setTimeout(() => {
          resolve("bar")
        }, 2000);
      })
    }

    async function demo() {
      console.log("demo function")
      return {
        then: function(resolve) {
          resolve("demo")
        }
      }
    }


    // 2.调用的入口async函数
    async function foo() {
      console.log("foo function")

      const res1 = await requestData("why")
      console.log("res1:", res1)

      const res2 = await test()
      console.log("res2:", res2)

      const res3 = await bar()
      console.log("res3:", res3)

      const res4 = await demo()
      console.log("res4:", res4)
    }

    foo()

Hilo único: cómo se ejecuta el código secuencialmente

Cada página abierta por el navegador se convertirá en un proceso. Habrá muchos subprocesos en un proceso, pero solo hay un subproceso que ejecuta JavaScript.

 let name = "why"
    name = "kobe"

    function bar() {
      console.log("bar function")
    }

    function foo() {
      console.log("foo function")
      // 1.在JavaScript内部执行
      // let total = 0
      // for (let i = 0; i < 1000000; i++) {
      //   total += i
      // }

      // 2.创建一个定时器
      setTimeout(() => {
        console.log("setTimeout")
      }, 10000);

      bar()
    }

    foo()

Hilo único: cómo se ejecuta el código asincrónico

Independientemente del tiempo establecido por el temporizador, el código posterior al temporizador se ejecutará primero.

 Cola de eventos, bucle de eventos.

Los temporizadores, el monitoreo de dom y las solicitudes de red se agregarán a la cola de eventos, y luego la cola de eventos ingresará los eventos en el contexto de ejecución en el orden de primero en entrar, primero en salir.

 

<body>

  <button>按钮</button>
  
  <script>

    const btn = document.querySelector("button")
    btn.onclick = function() {
      console.log("btn click event")
    }

    console.log("Hello World")
    let message = "aaaa"
    message = "bbbb"

    setTimeout(() => {
      console.log("10s后的setTimeout")
    }, 0);

    console.log("Hello JavaScript")
    console.log("代码继续执行~~~")
    console.log("-------------")

  </script>

</body>

Hilo único: la diferencia entre microtareas y macrotareas

Las funciones dentro de la promesa son las mismas que las funciones escritas fuera: se ejecutan inmediatamente y no se colocan en la cola de eventos. Pero si esta promesa se ejecuta resolver o rechazar, el código de la función de devolución de llamada y catch se colocará en la cola.

El código del temporizador se colocará en la macrotarea y el código de entonces se colocará en la microtarea.

La división de macrotareas y microtareas está estipulada y no la elegimos nosotros.

 

El propósito de las microtareas es ejecutarlas antes que las macrotareas, por lo que las microtareas se ejecutan antes que las macrotareas.

  console.log("script start")

    // function bar() {
    //   console.log("bar function")
    // }

    // function foo() {
    //   console.log("foo function")
    //   bar()
    // }
    // foo()

    // 定时器
    setTimeout(() => {
      console.log("setTimeout0")
    }, 0)
    setTimeout(() => {
      console.log("setTimeout1")
    }, 0)

    // Promise中的then的回调也会被添加到队列中
    console.log("1111111")
    new Promise((resolve, reject) => {
      console.log("2222222")
      console.log("-------1")
      console.log("-------2")
      resolve()
      console.log("-------3")
    }).then(res => {
      console.log("then传入的回调: res", res)
    })
    console.log("3333333")

    console.log("script end")

Secuencia de ejecución de código: pregunta 1 de la entrevista (importante)

Tenga en cuenta que las funciones ordinarias y las funciones de devolución de llamada de promesa se ejecutan directamente en el contexto de ejecución, y el código en las devoluciones de llamada de resolución y rechazo de promesa y captura se ejecuta en microtareas.

Las microtareas se ejecutan antes que las macrotareas.

La mejor manera es dibujar el orden de ejecución de la cola de macrotareas y la cola de microtareas.

 

 Si hay microtareas en la microtarea, la macrotarea se retrasará hasta su ejecución, independientemente de si la microtarea se completó antes. Cuando se ejecuta la macrotarea, si se crea la microtarea (la macrotarea se ha ejecutado, solo se puede decir que la microtarea ha terminado), una vez completada esta macrotarea, vuelva inmediatamente a ejecutar la microtarea .

 Secuencia de ejecución final:

 

 console.log("script start")

    setTimeout(function () {
      console.log("setTimeout1");
      new Promise(function (resolve) {
        resolve();
      }).then(function () {
        new Promise(function (resolve) {
          resolve();
        }).then(function () {
          console.log("then4");
        });
        console.log("then2");
      });
    });

    new Promise(function (resolve) {
      console.log("promise1");
      resolve();
    }).then(function () {
      console.log("then1");
    });

    setTimeout(function () {
      console.log("setTimeout2");
    });

    console.log(2);

    queueMicrotask(() => {
      console.log("queueMicrotask1")
    });

    new Promise(function (resolve) {
      resolve();
    }).then(function () {
      console.log("then3");
    });

    console.log("script end")

Secuencia de ejecución de código: código de espera

Si luego se ejecuta en una macrotarea, primero se ejecutará la macrotarea que envuelve entonces y luego la microtarea.

El cronómetro también se divide en tiempo y macrotareas avanzadas con poco tiempo.

 Antes de que await obtenga el resultado, el código posterior en este ámbito no se ejecutará y se omitirá. Y el código detrás de await en el mismo alcance es equivalente al código de entonces, que se coloca en microtareas.

 

 console.log("script start")

    function requestData(url) {
      console.log("requestData")
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log("setTimeout")
          resolve(url)
        }, 2000);
      })
    }

    // 2.await/async
    async function getData() {
      console.log("getData start")
      const res = await requestData("why")
      
      console.log("then1-res:", res)
      console.log("getData end")
    }

    getData()
    
    console.log("script end")

    // script start
    // getData start
    // requestData
    // script end

    // setTimeout

    // then1-res: why
    // getData end

Secuencia de ejecución de código: pregunta 2 de la entrevista

Cuando se ejecuta async2 () en la figura siguiente, se llamará a la función asunc2. Aunque solo se imprime async2, hay un retorno oculto indefinido, que es equivalente a resolver (indefinido) y console.log ('async1 end') will Se agrega a la microtarea porque equivale a colocarse en then .

 Nota: El código de await async2() se ejecutará como código normal como console.log('async1 start'), y await async2() es una función, necesita encontrar esa función y luego saltar a esta función para ejecutar código en el interior.

 

 

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

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

    console.log('script start')

    setTimeout(function () {
      console.log('setTimeout')
    }, 0)
    
    async1();
    
    new Promise (function (resolve) {
      console.log('promise1')
      resolve();
    }).then (function () {
      console.log('promise2')
    })

    console.log('script end')

Manejo de excepciones: manejo de errores predeterminado

Si el navegador informa un error, el código después de la línea del código fuente del error no se ejecutará. Entonces es peligroso.

Una solución es lanzar excepciones activamente y utilizar la palabra clave throw. Pero el código después del lanzamiento no se ejecutará. La ventaja es que puede generar su descripción personalizada del problema.

 

 // 1.遇到一个错误, 造成后续的代码全部不能执行
    // function foo() {
    //   "abc".filter()

    //   console.log("第15行代码")
    //   console.log("-------")
    // }

    // foo()
    // console.log("+++++++++")

    // const btn = document.querySelector("button")
    // btn.onclick = function() {
    //   console.log("监听btn的点击")
    // }

    // 2.自己封装一些工具
    function sum(num1, num2) {
      if (typeof num1 !== "number") {
        throw "type error: num1传入的类型有问题, 必须是number类型"
      }

      if (typeof num2 !== "number") {
        throw "type error: num2传入的类型有问题, 必须是number类型"
      }

      return num1 + num2
    }

    // 李四调用
    const result = sum(123, 321)

Manejo de excepciones: lanzar lanza una excepción

El mensaje de lanzar una excepción es una oración y no tiene ningún efecto, generalmente se usa el tipo de objeto para lanzarlo y se puede mostrar más contenido. Por supuesto, también puedes personalizar la clase para escribir mensajes de error.

El sistema también ha escrito clases de error que se pueden usar directamente. 

  class HYError {
      constructor(message, code) {
        this.errMessage = message
        this.errCode = code
      }
    }

    // throw抛出一个异常
    // 1.函数中的代码遇到throw之后, 后续的代码都不会执行
    // 2.throw抛出一个具体的错误信息
    function foo() {
      console.log("foo function1")
      // 1.number/string/boolean
      // throw "反正就是一个错误"

      // 2.抛出一个对象
      // throw { errMessage: "我是错误信息", errCode: -1001 }
      // throw new HYError("错误信息", -1001)

      // 3.Error类: 错误函数的调用栈以及位置信息
      throw new Error("我是错误信息")

      console.log("foo function2")
      console.log("foo function3")
      console.log("foo function4")
    }

    function bar() {
      foo()
    }

    bar()

 

Manejo de excepciones: cómo detectar excepciones

¿Por qué una vez que ocurre un error, el código posterior no se ejecuta?

Esto se debe a que el error se informa capa por capa desde el lugar donde se informa el error, y eventualmente se generará un error en el navegador, por lo que se interrumpirá la ejecución del código posterior. Si escribimos el código para capturar y procesar el error, el código subsiguiente puede continuar ejecutándose.

finalmente es seguro que se ejecutará

 function foo() {
      console.log("foo function1")
      // throw new Error("我是错误信息")
      console.log("foo function2")
      console.log("foo function3")
      console.log("foo function4")
    }

    function test() {
      // 自己捕获了异常的话, 那么异常就不会传递给浏览器, 那么后续的代码可以正常执行
      try {
        foo()
        console.log("try后续的代码")
      } catch(error) {
        console.log("catch中的代码")
        // console.log(error)
      } finally {
        console.log("finally代码")
      }
    }

    function bar() {
      test()
    }

    bar()

    console.log("--------")

Después de escribir un try catch para detectar la excepción, el código posterior se puede ejecutar normalmente.

 

Supongo que te gusta

Origin blog.csdn.net/weixin_56663198/article/details/131728637
Recomendado
Clasificación