JavaScript asynchrone

fil unique

Un seul thread signifie qu’il n’y a qu’un seul thread d’exécution dans un programme. Dans un programme monothread, toutes les tâches sont exécutées dans l'ordre, c'est-à-dire que chaque tâche doit attendre la fin de la tâche précédente avant de pouvoir commencer son exécution. Cette méthode est appelée exécution en série car toutes les tâches sont exécutées séquentiellement dans le même thread. Dans un programme monothread, toutes les opérations sont synchronisées.

Avantages et inconvénients : L'avantage du monothreading est que le code est simple et facile à comprendre, car tous les codes sont exécutés dans l'ordre. De plus, comme il n’y a qu’un seul thread en cours d’exécution, il n’est pas nécessaire de prendre en compte les problèmes de synchronisation entre les threads, ce qui peut réduire l’apparition de certains problèmes de concurrence. Les inconvénients du monothreading sont également évidents, le plus gros inconvénient étant les problèmes de performances.

file d'attente asynchrone

Une file d'attente asynchrone est une structure de données utilisée pour gérer des tâches asynchrones. Il est généralement utilisé dans les programmes multithread ou multi-processus pour gérer certaines tâches fastidieuses, telles que les requêtes réseau, la lecture et l'écriture de fichiers, etc. Les files d'attente asynchrones permettent aux programmes d'exécuter des tâches asynchrones sans bloquer l'exécution d'autres tâches.
Les tâches de la file d'attente asynchrone seront placées dans une file d'attente et exécutées dans l'ordre premier entré, premier sorti . Dans une file d'attente asynchrone, l'exécution des tâches est complétée par un pool de threads ou de processus. Lorsqu'une tâche est ajoutée à la file d'attente, le pool de threads ou de processus vérifiera s'il existe actuellement des threads ou des processus inactifs disponibles, et si tel est le cas, la tâche sera immédiatement affectée à l'un des threads ou processus pour exécution. Si aucun thread ou processus inactif n'est actuellement disponible, la tâche attend qu'un seul soit disponible.
Bien que la file d'attente asynchrone puisse améliorer l'efficacité du programme, elle ne garantit pas l'ordre d'exécution des tâches . Si l'ordre d'exécution des tâches affecte l'exactitude du programme, d'autres méthodes doivent être utilisées pour garantir l'ordre des tâches.

Rappeler

La fonction de rappel est une technique de programmation courante qui permet d'appeler une autre fonction ou méthode pour un traitement ultérieur après l'exécution d'une fonction ou d'une méthode. Une fonction de rappel est généralement transmise en tant que paramètre à la fonction d'origine pour être appelée une fois l'exécution de la fonction d'origine terminée.

Les fonctions de rappel sont souvent utilisées dans les modèles de programmation pilotés par événements. Par exemple, dans le développement Web, lorsque l'utilisateur clique sur un bouton, le navigateur déclenche un événement et le développeur peut enregistrer une fonction de rappel dans le gestionnaire d'événements pour effectuer des actions supplémentaires lorsque l'événement se produit. Dans ce cas, la fonction de rappel est généralement définie comme une fonction indépendante qui peut être appelée lorsque l'événement se produit pour terminer l'opération correspondante.

Générateur et Async/Await

Le générateur est une fonction spéciale qui peut suspendre l'exécution pendant l'exécution et reprendre l'exécution en cas de besoin. Generator implémente ce mécanisme de pause et de reprise en utilisant le mot-clé rendement. Lorsque la fonction génératrice atteint une instruction rendement, elle suspend l'exécution et renvoie une valeur, en attendant le prochain appel pour reprendre l'exécution.

Les générateurs du modèle de programmation asynchrone sont souvent appelés « coroutines ». Ils peuvent être mis en pause et repris pendant l'exécution et peuvent être utilisés pour gérer des événements et des opérations asynchrones. L'utilisation de coroutines peut rendre la programmation asynchrone plus concise et lisible, et peut également éviter le problème du trop grand nombre de fonctions de rappel imbriquées.

En JavaScript, Async/Await est un modèle de programmation asynchrone basé sur Generator. L'utilisation d'Async/Await peut rendre la programmation asynchrone plus simple et plus intuitive, évitant ainsi les problèmes d'imbrication des fonctions de rappel et de gestion des erreurs. Dans Async/Await,utilisez le mot-clé async pour déclarer une fonction asynchrone. À l'intérieur de la fonction, vous pouvez utiliser le mot-clé wait pour attendre la fin de l'opération asynchrone et renvoyer le résultat.

L'idée principale de Generator et Async/Await est de permettre au programme de suspendre et de reprendre son exécution pendant l'exécution d'opérations asynchrones. L'utilisation de Generator ou Async/Await peut rendre la programmation asynchrone plus concise et lisible, et peut également éviter les problèmes d'imbrication des fonctions de rappel et de gestion des erreurs.

Promesse

Promise est une solution de programmation asynchrone qui peut éviter les problèmes d'imbrication des fonctions de rappel et de gestion des erreurs, rendant la programmation asynchrone plus simple et plus intuitive. Un objet Promise représente l'achèvement ou l'échec final d'une opération asynchrone, et plusieurs opérations asynchrones peuvent être appelées dans une chaîne.

En JavaScript, Promise est un constructeur qui utilise le nouveau mot-clé pour créer une instance Promise. Le constructeur de Promise accepte une fonction comme paramètre, qui accepte deux paramètres : résoudre et rejeter. Lorsque l'opération asynchrone se termine avec succès, la fonction de résolution est appelée et le résultat de l'opération asynchrone est transmis ; lorsque l'opération asynchrone échoue, la fonction de rejet est appelée et le message d'erreur est transmis.

Les instances de promesse ont trois états : en attente , remplie et rejetée . Lorsque l'objet Promise est créé pour la première fois, son statut est en attente. Lorsqu'une opération asynchrone se termine avec succès, le statut de l'objet Promise passe à Réalisé ; lorsqu'une opération asynchrone échoue, le statut de l'objet Promise passe à Rejeté. Une fois que l’état d’un objet Promise change, il ne change plus jamais.

Promise peut être utilisée pour enchaîner plusieurs opérations asynchrones, en utilisant les méthodes then et catch pour gérer les situations de réussite et d'échec. La méthode then accepte deux paramètres, le premier paramètre est une fonction de rappel de réussite et le deuxième paramètre est une fonction de rappel d'échec ; la méthode catch accepte un paramètre pour gérer l'échec.

En bref, Promise est une solution pour la programmation asynchrone, qui peut éviter les problèmes de fonctions de rappel imbriquées et de gestion des erreurs, rendant la programmation asynchrone plus simple et plus intuitive. Un objet Promise représente l'achèvement ou l'échec final d'une opération asynchrone, et plusieurs opérations asynchrones peuvent être appelées dans une chaîne. Utilisez les méthodes then et catch pour gérer les situations de réussite et d’échec.

Promesse manuscrite

Ce qui suit est un code de mise en œuvre de base de Promise pour démontrer le principe de mise en œuvre 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);
      }
    });
  }
}

Ce code d'implémentation de Promise inclut , then, catch, resolveet ces méthodes. La méthode est utilisée pour enregistrer les fonctions de rappel de réussite et d'échec, la méthode est utilisée pour enregistrer la fonction de rappel d'échec, la méthode est utilisée pour créer un objet Promise qui se résout avec une valeur donnée, la méthode est utilisée pour créer un objet Promise qui est rejeté pour une raison donnée, la méthode est utilisée Méthode pour créer un objet Promise qui se résout lorsque tous les objets Promise donnés sont résolus avec succès, et rejette lorsqu'un objet Promise donné est rejeté, la méthode est utilisée pour créer un objet Promise qui se résout lorsqu'une promesse donnée l'objet est résolu. Il sera résolu ou rejeté lorsqu'il sera rejeté.rejectallracethencatchresolverejectallrace

Notez que ce code d'implémentation de Promise n'est qu'une simple implémentation et qu'il ne prend pas en compte certains problèmes clés, tels que la gestion des erreurs, les problèmes de performances, les problèmes de sécurité, etc. Dans le développement réel, nous devons utiliser une implémentation Promise plus complète et plus robuste, ou utiliser directement l'objet Promise intégré du navigateur ou de Node.js.

Je suppose que tu aimes

Origine blog.csdn.net/qq_48439911/article/details/130507458
conseillé
Classement