JS asincrónico: principio de ejecución y devolución de llamada

JS asincrónico: principio de ejecución y devolución de llamada



1. El principio de ejecución asincrónica de JS

  Sabemos que JavaScript es de un solo subproceso , mientras que los navegadores son de varios subprocesos . Las tareas de ejecución de un solo subproceso deben ponerse en cola una por una. Si una tarea tarda mucho en ejecutarse (como ajax tarda mucho tiempo), no provocará directamente ninguna respuesta y las siguientes tareas han estado esperando su ejecución. En este momento, debe utilizar la asincronía.

  Para entender la asincronía, primero tenemos que saber que los navegadores tienen tres temas básicos: residentes de rosca JS motor , hilo activación de un evento , y de hilo de representación GUI .

  El subproceso del motor JS y el subproceso desencadenante de eventos juntos constituyen un mecanismo de bucle de eventos , y el subproceso de representación de la GUI y el motor JS son mutuamente excluyentes. Cuando se ejecuta el motor JS, el subproceso de la GUI se suspenderá y las actualizaciones de la GUI se almacenarán en una cola. Cuando el motor JS está inactivo, se ejecuta inmediatamente.

  Analizamos desde su mecanismo de bucle de eventos: Los Inserte la descripción de la imagen aquí
  subprocesos del motor JS se dividen en tareas sincrónicas y asincrónicas:

    1. Todas las tareas de sincronización se ejecutan a través del hilo principal para formar una pila de ejecución .
    2. Cuando haya una tarea asincrónica, entréguela al proceso asincrónico (WebAPI): Incluyendo el subproceso de activación de eventos o el procesamiento del subproceso del temporizador para formar una cola de tareas .
    3. Cuando se procesan todas las tareas en la pila de ejecución y el subproceso principal está inactivo, las tareas se extraerán de la cola de tareas a la pila de ejecución para su ejecución.

  En términos sencillos, además del subproceso principal, JavaScript también tiene una cola de tareas. La cola de tareas almacena contenido que debe ejecutarse de forma asincrónica. Una vez que se ejecuta el subproceso principal, continuará escaneando y ejecutando las tareas en la cola de tareas hasta que se vacíe la cola.

Dibujar solución:


Inserte la descripción de la imagen aquí

  Como se muestra en la imagen, Xiaoming no podrá jugar el juego DNF si le toma mucho tiempo aprender, por lo que coloca el aprendizaje en la cola de tareas asincrónicas y luego aprende (cola de tareas) después de jugar el juego (hilo principal) . Durante el período, la madre agregó eventos de aprendizaje (eventos DOM) y Xiaoming verificaba qué otras tareas eran (escaneo cíclico) cada vez que Xiaoming completaba una tarea de aprendizaje, hasta la finalización final.


  Veamos otro ejemplo (el navegador se actualiza y sigue haciendo clic en el botón):

      let myData = null
      //ajax请求
      function ajax() {
    
    
      //腾讯新冠实时数据接口,仅做学习
        axios.get('https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=chinaDayList,chinaDayAddList,nowConfirmStatis,provinceCompare')
          .then(data => {
    
    
            console.log("ajax返回成功");
            myData = data.data
            console.log(myData);

          })
          .catch(error => {
    
    
            console.log("ajax返回失败");
          })
      }
      console.log(myData);
      ajax()
      setTimeout(() => {
    
    
        console.log('定时器');
      }, 2000);
      console.log(myData);
      const btn = document.querySelector('button')
      btn.onclick = () => {
    
    
        console.log("点击了");
      }

nulo
nulo
ajax devuelve éxito
Objeto
pulsado
Temporizador
pulsado

  Se puede ver que la consola se ejecuta sincrónicamente en el hilo principal y se ejecuta primero, mientras que la cola de tareas fuera del hilo principal almacena el contenido de la ejecución asíncrona. Aquí están los eventos setTimeout, ajax y DOM, que se ejecutan en el orden del cola de tareas ( cola de exploración cíclica) .
  
  ¿Por qué quiere escanear en bucle?

  Se puede ver en el evento de clic que cuando el usuario interactúa (evento de clic, evento de desplazamiento, evento de cambio de tamaño de ventana, etc.), se agregarán nuevos eventos a la cola de tareas en el bucle de eventos y luego se esperará la ejecución, por lo que Se requiere escaneo cíclico.

Dos, devoluciones de llamada en JS asincrónico


  Dado que la asincronía se ejecuta en la última cola de tareas, gran parte de nuestra lógica es difícil de implementar. En este momento, debemos lidiar con esta lógica asincrónica. El método más utilizado es la devolución de llamada .

Función de devolución de llamada: en pocas palabras, cuando la función A se pasa en la función B como parámetro, la función B es la función de devolución de llamada ejecutada por la función A. Hay dos tipos de devoluciones de llamada: devoluciones de llamada anidadas y devoluciones de llamada encadenadas.


  Aquí hay un uso simple de devolución de llamada:

      let myData = null
      console.log(myData);
      setTimeout(() => {
    
    
        console.log('定时器');
      }, 2000);
      const btn = document.querySelector('button')
      btn.onclick = () => {
    
    
        console.log("点击了");
      }
      let name = "张三"
      function hr(callback) {
    
    
        setTimeout(() => {
    
    
          console.log(`我是${
      
      name}`);
          callback();
        }, 2001);
      }
      console.log(myData);
      function gj() {
    
    
        console.log(`${
      
      name}你好,我是李四,认识一下吧`);
      }
      hr(gj)

null
null temporizador de
clics Soy Zhang San Zhang San Hola, soy Li Si, vamos a saber que hiciste clic



  Obviamente, usamos devoluciones de llamada cuando nuestras funciones necesitan datos, y aquí se usan devoluciones de llamada asíncronas.

  Aunque la devolución de llamada es un método común para resolver problemas asincrónicos, va acompañada de las cada vez más complejas necesidades de JS. Sincrónico y asincrónico requieren cada vez más lógica de implementación de devolución de llamada. La mezcla de anidación y sangría de devolución de llamada sincrónica y asincrónica y excesiva hace que el código sea difícil de interpretar y mantener, formando un "infierno de devolución de llamada" .

Inserte la descripción de la imagen aquí

  Veamos un ejemplo:

const verifyUser = function(username, password, callback){
    
    
   dataBase.verifyUser(username, password, (error, userInfo) => {
    
    
       if (error) {
    
    
           callback(error)
       }else{
    
    
           dataBase.getRoles(username, (error, roles) => {
    
    
               if (error){
    
    
                   callback(error)
               }else {
    
    
                   dataBase.logAccess(username, (error) => {
    
    
                       if (error){
    
    
                           callback(error);
                       }else{
    
    
                           callback(null, userInfo, roles);
                       }
                   })
               }
           })
       }
   })
};

La mayoría de la gente simplemente ve el código anterior y siente el sabor de su cerebro congelado.Si hay cientos de estos bloques de código en un proyecto, después de un período de tiempo, creo que incluso las personas que lo escribieron tendrán dolor de cabeza. Venir a tu propio proyecto es como ir al infierno.

  Lo más importante es que, al mismo tiempo, la devolución de llamada todavía tiene un problema de confianza y le da el control de ejecución a un tercero (como ajax). Para resolver el problema de confianza, debemos escribir varias lógicas en el programa para resolver el problema de confianza causado por las devoluciones de llamada.
  · La llamada es demasiado pronto
  · La llamada ha terminado
  · La cantidad de llamadas es demasiada o muy pocas, y los parámetros requeridos no se pasan correctamente a la función de devolución de llamada
  · Se tragan los posibles errores.

  Se puede encontrar que escribir lógica específica para resolver problemas de confianza específicos lo ha hecho más difícil que su propio valor de aplicación, y también causará problemas como redundancia de código y mala legibilidad.


  En resumen: las devoluciones de llamada resuelven los defectos de la asincrónica:
     1) No se ajusta al pensamiento lógico del procesamiento de tareas de las personas
     2) El problema de confianza causado por las devoluciones de llamada.


  Frente a los inconvenientes cada vez más obvios de las devoluciones de llamada, ES6 ha actualizado Promises para resolver problemas asincrónicos. El siguiente artículo escribe ES6-Promise.

Supongo que te gusta

Origin blog.csdn.net/Zxinxxx/article/details/114444890
Recomendado
Clasificación