Maison > interface Web > js tutoriel > le corps du texte

Comment convertir les rappels JavaScript en promesses ? Présentation de la méthode

青灯夜游
Libérer: 2020-12-03 17:48:12
avant
5526 Les gens l'ont consulté

Comment convertir les rappels JavaScript en promesses ? Présentation de la méthode

Il y a quelques années, les rappels étaient le seul moyen d'exécuter du code asynchrone en JavaScript. Il y a peu de problèmes avec les rappels eux-mêmes, le plus notable étant « l’enfer des rappels ».

Introduit dans ES6 Promesse comme solution à ces problèmes. Enfin, le mot-clé async/await est introduit pour offrir une meilleure expérience et améliorer la lisibilité.

Même avec les nouvelles méthodes, il existe encore de nombreux modules et bibliothèques natifs qui utilisent des rappels. Dans cet article, nous verrons comment convertir les rappels JavaScript en promesses. La connaissance d'ES6 sera utile, car nous utiliserons des fonctionnalités telles que l'opérateur de propagation pour simplifier ce que nous devons faire.

Qu'est-ce qu'un rappel ?

Un rappel est un paramètre de fonction, qui se trouve être une fonction elle-même. Bien que nous puissions créer n'importe quelle fonction pour accepter une autre fonction, les rappels sont principalement utilisés pour les opérations asynchrones.

JavaScript est un langage interprété qui ne peut traiter qu'une seule ligne de code à la fois. Certaines tâches peuvent prendre beaucoup de temps, comme le téléchargement ou la lecture de fichiers volumineux, etc. JavaScript décharge ces tâches de longue durée vers le navigateur ou d'autres processus au sein de l'environnement Node.js. De cette façon, cela ne bloquera pas l’exécution d’autres codes.

Habituellement, les fonctions asynchrones acceptent les fonctions de rappel afin que leurs données puissent être traitées une fois terminées.

Par exemple, nous écrirons une fonction de rappel qui sera exécutée une fois que le programme aura lu avec succès le fichier sur le disque dur.

Vous devez donc préparer un fichier texte nommé sample.txt, qui contient le contenu suivant :

Hello world from sample.txt
Copier après la connexion

Ensuite, écrivez un simple script Node.js pour lire le fichier :

const fs = require('fs');

fs.readFile('./sample.txt', 'utf-8', (err, data) => {
    if (err) {
        // 处理错误
        console.error(err);
          return;
    }
    console.log(data);
});

for (let i = 0; i < 10; i++) {
    console.log(i);
}
Copier après la connexion

Après avoir exécuté le code, il affichera :

0
...
8
9
Hello world from sample.txt
Copier après la connexion

Si vous utilisez ce code, vous devriez voir 0..9 être affiché sur la console avant d'exécuter le rappel. Cela est dû au mécanisme de gestion asynchrone de JavaScript. Après avoir lu le fichier, le rappel pour afficher le contenu du fichier est appelé.

À propos, les rappels peuvent également être utilisés dans les méthodes synchrones. Par exemple, Array.sort() acceptera une fonction de rappel qui vous permettra de personnaliser la façon dont les éléments sont triés.

Les fonctions qui acceptent les rappels sont appelées « fonctions d'ordre supérieur ».

Nous disposons désormais d'une meilleure méthode de rappel. Continuons donc à regarder ce qu'est Promise.

Qu'est-ce que Promise

Promise a été introduit dans ECMAScript 2015 (ES6) pour améliorer l'expérience de programmation asynchrone. Comme son nom l'indique, la « valeur » ou « l'erreur » qu'un objet JavaScript renverra éventuellement doit être une promesse.

Une promesse a 3 états :

  • En attente (en attente)  : Un état initial utilisé pour indiquer que l'opération asynchrone n'est pas encore terminée.
  • Réalisé  : Indique que l'opération asynchrone s'est terminée avec succès.
  • Rejeté  : Indique que l'opération asynchrone a échoué.

La plupart des promesses finissent par ressembler à ceci :

someAsynchronousFunction()
    .then(data => {
        // promise 被完成
        console.log(data);
    })
    .catch(err => {
        // promise 被拒绝
        console.error(err);
    });
Copier après la connexion

Les promesses sont très importantes dans le JavaScript moderne car elles sont liées au introduit dans ECMAScript 2016async/await Les mots-clés sont utilisés ensemble. L'utilisation de async / await élimine le besoin de rappels ou de then() et catch() pour écrire du code asynchrone.

Si vous deviez réécrire l'exemple précédent, il ressemblerait à ceci :

try {
    const data = await someAsynchronousFunction();
} catch(err) {
    // promise 被拒绝
    console.error(err);
}
Copier après la connexion

Cela ressemble beaucoup à du JavaScript synchrone "normal". Les bibliothèques JavaScript les plus populaires et les nouveaux projets utilisent Promises avec le mot-clé async/await.

Cependant, si vous mettez à jour une bibliothèque existante ou si vous rencontrez du code ancien, vous pourriez être intéressé par la migration d'une API basée sur le rappel vers une API basée sur la promesse, ce qui peut améliorer votre expérience de développement.

Examinons plusieurs façons de convertir les rappels en promesse.

Convertir les rappels en Promise

Promesse Node.js

La plupart des fonctions asynchrones qui acceptent les rappels dans Node.js (comme le module fs) ont des implémentations standard Méthode : Passez le rappel comme dernier paramètre.

Par exemple, voici comment lire un fichier avec fs.readFile() sans spécifier l'encodage du texte :

fs.readFile('./sample.txt', (err, data) => {
    if (err) {
        console.error(err);
          return;
    }
    console.log(data);
});
Copier après la connexion

Remarque : Si vous spécifiez utf-8 comme encodage, alors la sortie obtenue est une chaîne. Si non spécifié, la sortie est Buffer.

De plus, le rappel passé à cette fonction doit accepter Error car il s'agit du premier argument. Il peut y avoir n'importe quel nombre de sorties par la suite.

Si vous avez besoin d'une fonction convertie en Promise pour suivre ces règles, vous pouvez utiliser util.promisify , qui est un module Node.js natif qui contient des rappels vers Promise.

Importez d'abord le module ʻutil` :

const util = require('util');
Copier après la connexion

Puis convertissez-le en promesse en utilisant la méthode promisify :

const fs = require('fs');
const readFile = util.promisify(fs.readFile);
Copier après la connexion

Maintenant, utilisez la fonction nouvellement créée comme promesse :

readFile('./sample.txt', 'utf-8')
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.log(err);
    });
Copier après la connexion

Alternativement, vous pouvez utiliser le mot-clé async/await donné dans l'exemple ci-dessous :

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

(async () => {
    try {
        const content = await readFile('./sample.txt', 'utf-8');
        console.log(content);
    } catch (err) {
        console.error(err);
    }
})();
Copier après la connexion

Vous ne pouvez utiliser le mot-clé async que dans les fonctions créées avec await. C'est également la raison pour laquelle des wrappers de fonctions sont utilisés. Les wrappers de fonctions sont également appelés expressions de fonction immédiatement invoquées.

如果你的回调不遵循这个特定标准也不用担心。 util.promisify() 函数可让你自定义转换是如何发生的。

注意: Promise 在被引入后不久就开始流行了。 Node.js 已经将大部分核心函数从回调转换成了基于 Promise 的API。

如果需要用 Promise 处理文件,可以用 Node.js 附带的库(https://nodejs.org/docs/lates...)。

现在你已经了解了如何将 Node.js 标准样式回调隐含到 Promise 中。从 Node.js 8 开始,这个模块仅在 Node.js 上可用。如果你用的是浏览器或早期版本版本的 Node,则最好创建自己的基于 Promise 的函数版本。

创建你自己的 Promise

让我们讨论一下怎样把回调转为  util.promisify() 函数的 promise。

思路是创建一个新的包含回调函数的 Promise 对象。如果回调函数返回错误,就拒绝带有该错误的Promise。如果回调函数返回非错误输出,就解决并输出 Promise。

先把回调转换为一个接受固定参数的函数的 promise 开始:

const fs = require('fs');

const readFile = (fileName, encoding) => {
    return new Promise((resolve, reject) => {
        fs.readFile(fileName, encoding, (err, data) => {
            if (err) {
                return reject(err);
            }

            resolve(data);
        });
    });
}

readFile('./sample.txt')
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.log(err);
    });
Copier après la connexion

新函数 readFile() 接受了用来读取 fs.readFile() 文件的两个参数。然后创建一个新的 Promise 对象,该对象包装了该函数,并接受回调,在本例中为 fs.readFile()

要  reject  Promise 而不是返回错误。所以代码中没有立即把数据输出,而是先 resolve 了Promise。然后像以前一样使用基于 Promise 的 readFile() 函数。

接下来看看接受动态数量参数的函数:

const getMaxCustom = (callback, ...args) => {
    let max = -Infinity;

    for (let i of args) {
        if (i > max) {
            max = i;
        }
    }

    callback(max);
}

getMaxCustom((max) => { console.log('Max is ' + max) }, 10, 2, 23, 1, 111, 20);
Copier après la connexion

第一个参数是 callback 参数,这使它在接受回调的函数中有点与众不同。

转换为 promise 的方式和上一个例子一样。创建一个新的 Promise 对象,这个对象包装使用回调的函数。如果遇到错误,就 reject,当结果出现时将会 resolve

我们的 promise 版本如下:

const getMaxPromise = (...args) => {
    return new Promise((resolve) => {
        getMaxCustom((max) => {
            resolve(max);
        }, ...args);
    });
}

getMaxCustom(10, 2, 23, 1, 111, 20)
    .then(max => console.log(max));
Copier après la connexion

在创建 promise 时,不管函数是以非标准方式还是带有许多参数使用回调都无关紧要。我们可以完全控制它的完成方式,并且原理是一样的。

总结

尽管现在回调已成为 JavaScript 中利用异步代码的默认方法,但 Promise 是一种更现代的方法,它更容易使用。如果遇到了使用回调的代码库,那么现在就可以把它转换为 Promise。

在本文中,我们首先学到了如何 在Node.js 中使用 utils.promisfy() 方法将接受回调的函数转换为 Promise。然后,了解了如何创建自己的 Promise 对象,并在对象中包装了无需使用外部库即可接受回调的函数。这样许多旧 JavaScript 代码可以轻松地与现代的代码库和混合在一起。

更多编程相关知识,请访问:编程学习!!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:segmentfault.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!