JavaScript コールバックを Promise に変換するにはどうすればよいですか?手法の紹介

青灯夜游
リリース: 2020-12-03 17:48:12
転載
5576 人が閲覧しました

JavaScript コールバックを Promise に変換するにはどうすればよいですか?手法の紹介

数年前までは、JavaScript で非同期コードを実行するにはコールバックが唯一の方法でした。コールバック自体にはほとんど問題はありませんが、最も顕著なのは「コールバック地獄」です。

これらの問題の解決策として、ES6 Promise で導入されました。最後に、async/await キーワードが導入され、エクスペリエンスが向上し、読みやすさが向上します。

新しいメソッドを使用しても、コールバックを使用するネイティブ モジュールやライブラリがまだたくさんあります。この記事では、JavaScript コールバックを Promise に変換する方法について説明します。スプレッド演算子のような機能を使用してやるべきことを簡素化するので、ES6 の知識が役に立ちます。

コールバックとは

コールバックは関数パラメータであり、関数自体になります。別の関数を受け入れる任意の関数を作成できますが、コールバックは主に非同期操作に使用されます。

JavaScript は、一度に 1 行のコードのみを処理できるインタープリター言語です。大きなファイルのダウンロードや読み取りなど、一部のタスクは完了するまでに時間がかかる場合があります。 JavaScript は、これらの長時間実行タスクをブラウザーまたは Node.js 環境内の他のプロセスにオフロードします。こうすることで、他のコードの実行がブロックされなくなります。

通常、非同期関数はコールバック関数を受け入れるため、完了後にデータを処理できます。

たとえば、プログラムがハードディスクからファイルを正常に読み取った後に実行されるコールバック関数を作成します。

したがって、次の内容を含む sample.txt という名前のテキスト ファイルを準備する必要があります。

Hello world from sample.txt
ログイン後にコピー

次に、ファイルを読み取るための簡単な Node.js スクリプトを作成します。 :

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);
}
ログイン後にコピー

コードを実行すると、次の出力が表示されます:

0
...
8
9
Hello world from sample.txt
ログイン後にコピー

このコードを使用すると、実行前に 0..9 がコンソールに出力されるはずです。コールバック。これは、JavaScript の非同期管理メカニズムによるものです。ファイルを読み取った後、ファイルの内容を出力するためのコールバックが呼び出されます。

ちなみに、コールバックは同期メソッドでも使用できます。たとえば、Array.sort() は、要素の並べ替えをカスタマイズできるコールバック関数を受け入れます。

コールバックを受け入れる関数は「高階関数」と呼ばれます。

これで、より良いコールバック メソッドが完成しました。それでは、Promise とは何かを見ていきましょう。

Promise とは

Promise は、非同期プログラミングのエクスペリエンスを向上させるために ECMAScript 2015 (ES6) で導入されました。名前が示すように、JavaScript オブジェクトが最終的に返す「値」または「エラー」は Promise である必要があります。

Promise には 3 つの状態があります。

  • Pending (保留中) : 初期状態は、非同期操作がまだ完了していないことを示すために使用されます。
  • Fulfilled: 非同期操作が正常に完了したことを示します。
  • Rejected: 非同期操作が失敗したことを示します。

ほとんどの Promise は最終的に次のようになります:

someAsynchronousFunction()
    .then(data => {
        // promise 被完成
        console.log(data);
    })
    .catch(err => {
        // promise 被拒绝
        console.error(err);
    });
ログイン後にコピー

Promise は、ECMAScript 2016 で導入された と同じであるため、最新の JavaScript では非常に重要です async/ を使用します。 await キーワードを一緒に使用します。 async / await を使用すると、コールバックや then() および catch() を使用した非同期コードを作成する必要がなくなります。

前の例を書き直すと、次のようになります。

try {
    const data = await someAsynchronousFunction();
} catch(err) {
    // promise 被拒绝
    console.error(err);
}
ログイン後にコピー
これは、「通常の」同期 JavaScript とよく似ています。最も一般的な JavaScript ライブラリと新しいプロジェクトは、

async/await キーワードを含む Promises を使用します。

ただし、既存のライブラリを更新する場合、または古いコードに遭遇した場合は、コールバック ベースの API を Promise ベースの API に移行することに興味があるかもしれません。これにより、開発エクスペリエンスが向上します。

コールバックを Promise に変換するいくつかの方法を見てみましょう。

コールバックを Promise に変換する

Node.js Promise

コールバックを受け入れる Node.js のほとんどの非同期関数 (

fs モジュールなど)これを行う標準的な方法は、コールバックを最後のパラメータとして渡すことです。

たとえば、テキスト エンコーディングを指定せずに

fs.readFile() を使用してファイルを読み取る方法は次のとおりです。

fs.readFile('./sample.txt', (err, data) => {
    if (err) {
        console.error(err);
          return;
    }
    console.log(data);
});
ログイン後にコピー

Note:エンコーディングとして utf-8 を指定すると、結果の出力は文字列になります。指定しない場合、出力は Buffer です。

さらに、この関数に渡されるコールバックは、

Error が最初のパラメータであるため、これを受け入れる必要があります。その後、任意の数の出力を行うことができます。

これらのルールに従うために関数を Promise に変換する必要がある場合は、Promise へのコールバックを含むネイティブ Node.js モジュールである util.promisify を使用できます。

最初に `util` モジュールをインポートします:

const util = require('util');
ログイン後にコピー
次に、

promisify メソッドを使用してそれを Promise に変換します:

const fs = require('fs');
const readFile = util.promisify(fs.readFile);
ログイン後にコピー
次に、新しく追加された作成された関数 Make Promise:

readFile('./sample.txt', 'utf-8')
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.log(err);
    });
ログイン後にコピー
または、次の例に示す

async/await キーワードを使用することもできます:

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);
    }
})();
ログイン後にコピー
使用できるのは

async# のみです## 作成された関数で await キーワードを使用します。これが、関数ラッパーが使用される理由です。関数ラッパーは、即時に呼び出される関数式とも呼ばれます。 <p>如果你的回调不遵循这个特定标准也不用担心。 <code>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);
    });
ログイン後にコピー

新函数 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);
ログイン後にコピー

第一个参数是 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));
ログイン後にコピー

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

总结

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

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

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

以上がJavaScript コールバックを Promise に変換するにはどうすればよいですか?手法の紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:segmentfault.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート