JavaScript asíncrono

hilo único

Un solo hilo significa que solo hay un hilo de ejecución en un programa. En un programa de un solo subproceso, todas las tareas se ejecutan en secuencia, es decir, cada tarea debe esperar a que se complete la tarea anterior antes de poder comenzar a ejecutarse. Este método se llama ejecución en serie porque todas las tareas se ejecutan secuencialmente en el mismo hilo. En un programa de un solo subproceso, todas las operaciones están sincronizadas.

Ventajas y desventajas: la ventaja del subproceso único es que el código es simple y fácil de entender, porque todos los códigos se ejecutan en secuencia. Además, dado que solo se está ejecutando un subproceso, no es necesario considerar problemas de sincronización entre subprocesos, lo que puede reducir la aparición de algunos problemas de concurrencia. Las desventajas del subproceso único también son obvias; la mayor desventaja son los problemas de rendimiento.

cola asincrónica

Una cola asincrónica es una estructura de datos que se utiliza para manejar tareas asincrónicas. Generalmente se usa en programas multiproceso o multiproceso para manejar algunas tareas que requieren mucho tiempo, como solicitudes de red, lectura y escritura de archivos, etc. Las colas asincrónicas permiten que los programas ejecuten tareas asincrónicas sin bloquear la ejecución de otras tareas.
Las tareas en la cola asincrónica se colocarán en una cola y se ejecutarán en orden de primero en entrar, primero en salir . En una cola asincrónica, la ejecución de la tarea la completa un subproceso o un grupo de procesos. Cuando se agrega una tarea a la cola, el grupo de subprocesos o procesos verifica si actualmente hay subprocesos o procesos inactivos disponibles y, de ser así, la tarea se asigna inmediatamente a uno de los subprocesos o procesos para su ejecución. Si no hay ningún subproceso o proceso inactivo disponible actualmente, la tarea espera hasta que haya uno disponible.
Aunque la cola asincrónica puede mejorar la eficiencia del programa, no garantiza el orden de ejecución de las tareas . Si el orden de ejecución de las tareas afecta la corrección del programa, entonces se deben utilizar otros métodos para garantizar el orden de las tareas.

Llamar de vuelta

La función de devolución de llamada es una técnica de programación común que permite llamar a otra función o método para su procesamiento posterior después de ejecutar una función o método. Una función de devolución de llamada generalmente se pasa como parámetro a la función original que se llamará después de que la función original haya completado su ejecución.

Las funciones de devolución de llamada se utilizan a menudo en modelos de programación basados ​​en eventos. Por ejemplo, en el desarrollo web, cuando el usuario hace clic en un botón, el navegador activa un evento y el desarrollador puede registrar una función de devolución de llamada en el controlador de eventos para realizar algunas acciones adicionales cuando ocurre el evento. En este caso, la función de devolución de llamada generalmente se define como una función independiente que se puede llamar cuando ocurre el evento para completar la operación correspondiente.

Generador y asíncrono/espera

El generador es una función especial que puede pausar la ejecución durante la ejecución y reanudarla cuando sea necesario. Generator implementa este mecanismo de pausa y reanudación utilizando la palabra clave de rendimiento. Cuando la función generadora llega a una declaración de rendimiento, pausa la ejecución y devuelve un valor, esperando la siguiente llamada para reanudar la ejecución.

Los generadores en el modelo de programación asincrónica a menudo se denominan "corrutinas", se pueden pausar y reanudar durante la ejecución y se pueden usar para manejar eventos asincrónicos y operaciones asincrónicas. El uso de corrutinas puede hacer que la programación asincrónica sea más concisa y legible, y también puede evitar el problema de demasiadas funciones de devolución de llamadas anidadas.

En JavaScript, Async/Await es un modelo de programación asincrónica basado en Generator. El uso de Async/Await puede hacer que la programación asincrónica sea más simple e intuitiva, evitando los problemas de anidamiento de funciones de devolución de llamada y manejo de errores. En Async/Await, use la palabra clave async para declarar una función asincrónica. Dentro de la función, puede usar la palabra clave await para esperar a que se complete la operación asincrónica y devolver el resultado.

La idea central de Generator y Async/Await es permitir que el programa se detenga y reanude la ejecución durante la ejecución de operaciones asincrónicas. El uso de Generator o Async/Await puede hacer que la programación asincrónica sea más concisa y legible, y también puede evitar los problemas de anidamiento de funciones de devolución de llamada y manejo de errores.

Promesa

Promise es una solución para la programación asincrónica que puede evitar los problemas de anidamiento de funciones de devolución de llamada y manejo de errores, haciendo que la programación asincrónica sea más simple e intuitiva. Un objeto Promise representa la finalización o falla final de una operación asincrónica, y se pueden llamar varias operaciones asincrónicas en una cadena.

En JavaScript, Promise es un constructor que utiliza la nueva palabra clave para crear una instancia de Promise. El constructor de Promise acepta una función como parámetro, que acepta dos parámetros: resolver y rechazar. Cuando la operación asincrónica se completa exitosamente, se llama a la función de resolución y se pasa el resultado de la operación asincrónica; cuando la operación asincrónica falla, se llama a la función de rechazo y se pasa el mensaje de error.

Las instancias de promesa tienen tres estados: pendiente , cumplida y rechazada . Cuando el objeto Promise se crea por primera vez, su estado es pendiente. Cuando una operación asincrónica se completa exitosamente, el estado del objeto Promise cambia a cumplido; cuando falla una operación asincrónica, el estado del objeto Promise cambia a rechazado. Una vez que el estado de un objeto Promise cambia, nunca vuelve a cambiar.

Promise se puede utilizar para encadenar múltiples operaciones asincrónicas, utilizando los métodos then y catch para manejar situaciones de éxito y fracaso. El método then acepta dos parámetros, el primer parámetro es una función de devolución de llamada exitosa y el segundo parámetro es una función de devolución de llamada fallida; el método catch acepta un parámetro para manejar la falla.

En resumen, Promise es una solución para la programación asincrónica, que puede evitar los problemas de las funciones de devolución de llamadas anidadas y el manejo de errores, haciendo que la programación asincrónica sea más simple e intuitiva. Un objeto Promise representa la finalización o falla final de una operación asincrónica, y se pueden llamar varias operaciones asincrónicas en una cadena. Utilice los métodos then y catch para manejar situaciones de éxito y fracaso.

Promesa manuscrita

El siguiente es un código de implementación básico de Promise para demostrar el principio de implementación de Promise:

class MyPromise {
    
    
  constructor(executor) {
    
    
    this.state = 'pending'; // 保存初始化状态
    this.value = null;  // 用于保存resolve传入的值
    this.reason = null;  // 用于保存rejected传入的值
    this.onFulfilledCallbacks = []; // 用于保存reslove的回调函数
    this.onRejectedCallbacks = [];  // 用于保存reject的回调函数
    
    //  状态变为resolved方法
    const resolve = value => {
    
    
      // 只有状态为pending 时才能改变
      if (this.state === 'pending') {
    
    
        this.state = 'fulfilled'; // 修改状态
        this.value = value;  // 设置传入的值
        this.onFulfilledCallbacks.forEach(callback => callback(value)); // 执行回调函数
      }
    };
  	
  	// 状态转变为rejected 方法
    const reject = reason => {
    
    
      // 只有状态为pending时才能转变
      if (this.state === 'pending') {
    
    
        this.state = 'rejected'; // 修改状态
        this.reason = reason;  // 设置传入的值
        this.onRejectedCallbacks.forEach(callback => callback(reason)); // 执行回调函数
      }
    };
  	// 将两个方法传入函数执行
    try {
    
    
      executor(resolve, reject);
    } catch (error) {
    
    
      // 遇到错误时,补货错误,执行reject函数
      reject(error);
    }
  }
  
  then(onFulfilled, onRejected) {
    
    
  	// 判断两个参数是否为函数类型,因为这两个参数是可选参数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {
    
     throw reason };
  	
  	// 封装前一个promise成功时执行的函数
    const promise2 = new MyPromise((resolve, reject) => {
    
    
      if (this.state === 'fulfilled') {
    
    
        setTimeout(() => {
    
    
          try {
    
    
            const x = onFulfilled(this.value);
            this.resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
    
    
            reject(error);
          }
        });
      }
  	  // 封装前一个promise失败时执行的函数
      if (this.state === 'rejected') {
    
    
        setTimeout(() => {
    
    
          try {
    
    
            const x = onRejected(this.reason);
            this.resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
    
    
            reject(error);
          }
        });
      }
  	  // 如果是等待状态,则将函数加入到对应列表中
      if (this.state === 'pending') {
    
    
        this.onFulfilledCallbacks.push(value => {
    
    
          setTimeout(() => {
    
    
            try {
    
    
              const x = onFulfilled(value);
              this.resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
    
    
              reject(error);
            }
          });
        });
  
        this.onRejectedCallbacks.push(reason => {
    
    
          setTimeout(() => {
    
    
            try {
    
    
              const x = onRejected(reason);
              this.resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
    
    
              reject(error);
            }
          });
        });
      }
    });
  
    return promise2;
  }
  
  catch(onRejected) {
    
    
    return this.then(null, onRejected);
  }
  
  resolvePromise(promise2, x, resolve, reject) {
    
    
    if (promise2 === x) {
    
    
      reject(new TypeError('Chaining cycle detected'));
    }
  
    if (x && (typeof x === 'object' || typeof x === 'function')) {
    
    
      let called = false;
  
      try {
    
    
        const then = x.then;
  
        if (typeof then === 'function') {
    
    
          then.call(
            x,
            y => {
    
    
              if (called) return;
              called = true;
              this.resolvePromise(promise2, y, resolve, reject);
            },
            reason => {
    
    
              if (called) return;
              called = true;
              reject(reason);
            }
          );
        } else {
    
    
          resolve(x);
        }
      } catch (error) {
    
    
        if (called) return;
        called = true;
        reject(error);
      }
    } else {
    
    
      resolve(x);
    }
  }
  
  // 如果状态凝固,则执行对应状态的函数
  static resolve(value) {
    
    
    if (value instanceof MyPromise) return value;
    return new MyPromise(resolve => resolve(value));
  }
  
  static reject(reason) {
    
    
    return new MyPromise((resolve, reject) => reject(reason));
  }
  
  // 接受一个Promise实例的数组或具有Iterator接口的对象作为参数
  // 参数其中一个失败,则触发失败状态,第一个触发失败的Promise错误的信息作为Promise.all的错误信息
  static all(promises) {
    
    
    return new MyPromise((resolve, reject) => {
    
    
      const values = [];
      let count = 0;
  
      for (let i = 0; i < promises.length; i++) {
    
    
        MyPromise.resolve(promises[i]).then(
          value => {
    
    
            values[i] = value;
            count++;
  
            if (count === promises.length) {
    
    
              resolve(values);
            }
          },
          reject
        );
      }
    });
  }
  // 该方法的参数是Promise的数组
  // 因为Promise的状态只能改变一次,我们需要把Promise.race中产生的Promise对象的resolve方法,
  // 注入到数组中的每一个Promise实例中的回调函数中即可。
  static race(promises) {
    
    
    return new MyPromise((resolve, reject) => {
    
    
      for (let i = 0; i < promises.length; i++) {
    
    
        MyPromise.resolve(promises[i]).then(resolve, reject);
      }
    });
  }
}

Este código de implementación de Promise incluye then, catch, resolve, y estos métodos. El método se usa para registrar funciones de devolución de llamada de éxito y falla, el método se usa para registrar la función de devolución de llamada de falla, el método se usa para crear un objeto Promise que se resuelve con un valor dado, el método se usa para crear un objeto Promise que es rechazado con un motivo determinado, se utiliza el método. Método para crear un objeto Promise que se resuelve cuando todos los objetos Promise dados se resuelven exitosamente, y rechaza cuando se rechaza cualquier objeto Promise dado. El método se usa para crear un objeto Promise que se resuelve cuando se rechaza cualquier objeto Promise. objeto resuelve Se resolverá o rechazará cuando sea rechazado.rejectallracethencatchresolverejectallrace

Tenga en cuenta que este código de implementación de Promise es solo una implementación simple y no tiene en cuenta algunas cuestiones clave, como el manejo de errores, problemas de rendimiento, problemas de seguridad, etc. En el desarrollo real, necesitamos utilizar una implementación de Promise más completa y robusta, o utilizar directamente el objeto Promise integrado del navegador o Node.js.

Supongo que te gusta

Origin blog.csdn.net/qq_48439911/article/details/130507458
Recomendado
Clasificación