Node.jsがpromiseのネイティブサポートを追加した後も、QやBlueBirdなどのライブラリを使用する理由はまだありますか?
たとえば、新しいプロジェクトを開始していて、このプロジェクトでこれらのライブラリを使用する依存関係がないと仮定すると、そのようなライブラリを使用する理由は本当にないと言えますか?
Node.jsがpromiseのネイティブサポートを追加した後も、QやBlueBirdなどのライブラリを使用する理由はまだありますか?
たとえば、新しいプロジェクトを開始していて、このプロジェクトでこれらのライブラリを使用する依存関係がないと仮定すると、そのようなライブラリを使用する理由は本当にないと言えますか?
回答:
古い格言は、あなたは仕事に適したツールを選ぶべきだと言っています。ES6 promiseは基本を提供します。あなたが望むか必要とするすべてが基本であるなら、それはあなたのためにうまくいくはずです/できます。ただし、ツールビンには、基本的なツールよりも多くのツールがあり、それらの追加のツールが非常に役立つ状況があります。また、ES6のプロミスには、ほぼすべてのnode.jsプロジェクトで役立つpromisificationなどの基本的な要素が欠けていることもあります。
私はBluebird promiseライブラリに最も精通しているので、そのライブラリでの私の経験から主に話をします。
それで、より有能なPromiseライブラリを使用する理由のトップ6を次に示します
インタフェース非同期非Promisified - .promisify()
とは、.promisifyAll()
1行のコードは、インターフェース全体のpromisifiedバージョンを作成します-まだ平野コールバックを必要とし、まだ約束を返さないすべてのそれらの非同期インターフェースを処理するのに非常に便利です。
非同期配列反復のシーケンス - Promise.mapSeries()
またはPromise.reduce()
、配列を反復処理して、各要素で非同期操作を呼び出しますが、非同期操作を順番に実行するので、すべてが同時に発生するわけではありません。これを行うことができるのは、宛先サーバーが要求するため、または1つの結果を次の結果に渡す必要があるためです。
ポリフィル -古いバージョンのブラウザクライアントでpromiseを使用する場合は、とにかくポリフィルが必要です。可能性のあるポリフィルも入手できます。node.jsにはES6のプロミスがあるため、node.jsにポリフィルは必要ありませんが、ブラウザで可能です。node.jsサーバーとクライアントの両方をコーディングする場合、両方に同じpromiseライブラリと機能を含めると非常に便利です(コードの共有、環境間のコンテキスト切り替え、非同期コードの一般的なコーディング手法の使用など)。 。)。
その他の便利な機能 -ブルーバードがありPromise.map()
、Promise.some()
、Promise.any()
、Promise.filter()
、Promise.each()
およびPromise.props()
すべてのは時折便利です。これらの操作はES6のプロミスと追加のコードで実行できますが、Bluebirdにはこれらの操作が事前にビルドおよびテストされているため、使用するコードがよりシンプルで少なくなります。
組み込みの警告と完全なスタックトレース -Bluebirdには、おそらく間違ったコードまたはバグである問題を警告する組み込みの警告がいくつかあります。たとえば、.then()
そのプロミスを返さずにハンドラ内に新しいプロミスを作成する関数を呼び出す場合(現在のプロミスチェーンにリンクするため)、ほとんどの場合、それは偶然のバグであり、Bluebirdは警告を表示します効果。その他の組み込みのBluebird警告は、ここで説明されています。
これらのさまざまなトピックの詳細は次のとおりです。
PromisifyAll
どのnode.jsプロジェクトでも、.promisifyAll()
モジュールのような標準のnode.jsモジュールで多く使用するため、どこでもすぐにBluebirdを使用しfs
ます。
Node.js自体は、fs
モジュールのように非同期IOを行う組み込みモジュールへのpromiseインターフェースを提供しません。したがって、これらのインターフェイスでpromiseを使用する場合は、使用する各モジュール関数の周囲にpromiseラッパーを手動でコーディングするか、promiseを使用するか使用しないライブラリを取得するかを選択できます。
ブルーバードのPromise.promisify()
とPromise.promisifyAll()
の約束を返すために大会の非同期APIを呼び出すのNode.jsの自動折り返しを提供しています。非常に便利で時間を節約できます。いつも使っています。
これがどのように機能するかの例です:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync('somefile.text').then(function(data) {
// do something with data here
});
代わりにfs
、使用したいAPI ごとに独自のpromiseラッパーを手動で作成することもできます。
const fs = require('fs');
function readFileAsync(file, options) {
return new Promise(function(resolve, reject) {
fs.readFile(file, options, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
readFileAsync('somefile.text').then(function(data) {
// do something with data here
});
また、使用するAPI関数ごとに手動でこれを行う必要があります。これは明らかに意味がありません。それは定型コードです。また、これを行うユーティリティを入手することもできます。Bluebird's Promise.promisify()
and Promise.promisifyAll()
はそのようなユーティリティです。
その他の便利な機能
以下は、私が特に便利だと思うBluebirdの機能の一部です(これらがコードを節約したり、開発をスピードアップしたりする方法について、以下にいくつかのコード例があります)。
Promise.promisify()
Promise.promisifyAll()
Promise.map()
Promise.reduce()
Promise.mapSeries()
Promise.delay()
その便利な機能にPromise.map()
加えて、同時に実行できる操作の数を指定できる同時実行オプションもサポートします。これは、実行することがたくさんあるが、外部を圧倒できない場合に特に便利です。資源。
これらの一部は、スタンドアロンと呼ばれることも、それ自体が反復可能コードに解決されて多くのコードを節約できるpromiseで使用されることもあります。
ポリフィル
ブラウザプロジェクトでは、Promiseをサポートしていない一部のブラウザを引き続きサポートしたいので、とにかくポリフィルが必要になります。jQueryも使用している場合は、jQueryに組み込まれているpromiseサポートを使用することもできます(ただし、いくつかの点でひどく非標準であり、おそらくjQuery 3.0で修正されています)。ただし、プロジェクトに重要な非同期アクティビティが含まれている場合は、 Bluebirdの拡張機能は非常に便利です。
もっと早く
また、BluebirdのPromiseは、V8に組み込まれているPromiseよりも大幅に高速であるように見えます。そのトピックの詳細については、この投稿を参照してください。
大きなものNode.jsがありません
node.js開発でBluebirdをあまり使用しないことを検討する理由は、node.jsがpromisify関数を組み込んでいるため、次のようなことができるということです。
const fs = requirep('fs');
fs.readFileAsync('somefile.text').then(function(data) {
// do something with data here
});
または、組み込みモジュールの一部としてすでに約束された方法を提供するだけです。
それまでは、Bluebirdでこれを行います。
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync('somefile.text').then(function(data) {
// do something with data here
});
ES6のpromiseサポートがnode.jsに組み込まれていて、組み込みモジュールのどれもpromiseを返さないのは少し奇妙に思われます。これは、node.jsで整理する必要があります。それまでは、Bluebirdを使用してライブラリ全体を約束します。つまり、組み込みモジュールのいずれも手動で最初にラッピングせずにプロミスを使用できないため、promiseはnode.jsに約20%実装されているように感じられます。
これが単純なPromiseとBluebirdの約束の例でありPromise.map()
、ファイルのセットを並行して読み取り、すべてのデータの処理が完了したときに通知する例です。
明白な約束
const files = ["file1.txt", "fileA.txt", "fileB.txt"];
const fs = require('fs');
// make promise version of fs.readFile()
function fsReadFileP(file, options) {
return new Promise(function(resolve, reject) {
fs.readFile(file, options, function(err, data) {
if (err) return reject(err);
resolve(data);
});
});
}
Promise.all(files.map(fsReadFileP)).then(function(results) {
// files data in results Array
}, function(err) {
// error here
});
ブルーバードPromise.map()
とPromise.promisifyAll()
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const files = ["file1.txt", "fileA.txt", "fileB.txt"];
Promise.map(files, fs.readFileAsync).then(function(results) {
// files data in results Array
}, function(err) {
// error here
});
以下は、単純なPromiseとBluebirdの約束の例でありPromise.map()
、一度に4つまで読み取ることができるが、できるだけ多くの要求を並行して保持したいリモートホストから一連のURLを読み取る場合の例です。
明白なJSの約束
const request = require('request');
const urls = [url1, url2, url3, url4, url5, ....];
// make promisified version of request.get()
function requestGetP(url) {
return new Promise(function(resolve, reject) {
request.get(url, function(err, data) {
if (err) return reject(err);
resolve(data);
});
});
}
function getURLs(urlArray, concurrentLimit) {
var numInFlight = 0;
var index = 0;
var results = new Array(urlArray.length);
return new Promise(function(resolve, reject) {
function next() {
// load more until concurrentLimit is reached or until we got to the last one
while (numInFlight < concurrentLimit && index < urlArray.length) {
(function(i) {
requestGetP(urlArray[index++]).then(function(data) {
--numInFlight;
results[i] = data;
next();
}, function(err) {
reject(err);
});
++numInFlight;
})(index);
}
// since we always call next() upon completion of a request, we can test here
// to see if there was nothing left to do or finish
if (numInFlight === 0 && index === urlArray.length) {
resolve(results);
}
}
next();
});
}
ブルーバードプロミス
const Promise = require('bluebird');
const request = Promise.promisifyAll(require('request'));
const urls = [url1, url2, url3, url4, url5, ....];
Promise.map(urls, request.getAsync, {concurrency: 4}).then(function(results) {
// urls fetched in order in results Array
}, function(err) {
// error here
});
return new Promise(function(resolve, rejct)
。する必要があります:reject
util.promisify
現在ありますが、直接対応promisifyAll
するものはありません。
fs
、Bluebirdを使用する他のいくつかの理由(私の特定のお気に入りはのconcurrency
オプションですPromise.map()
)で、多数の並列リクエストを行う必要があるターゲットサービスを圧倒しないようにします。また、BluebirdのpromisifyAllを使用するために、他の多くの約束されていないインターフェースがまだあります。しかし、node.js自体が組み込みのpromiseサポートを強化するにつれて、新しいプロジェクトごとにBluebirdをすぐに入手する理由は徐々に消えていきます。