更新中の古いNode.jsコードがいくつかあります。その過程で、古いコードで動作する新しいモジュールを設計しています。私がこれを最初に書いたときとは対照的に、私は今、コールバックではなくES6プロミスの使用に依存していることを発見しています。だから今、私は約束を返すいくつかの関数とコールバックを取るいくつかのこのミックスを持っています-これは退屈です。最終的には、Promiseを使用するようにリファクタリングする必要があると思います。しかし、それが行われる前に...
約束が優先され、コールバックが優先される状況は何ですか?
コールバックが約束よりもうまく処理できる状況と、その逆の状況はありますか?
これまで見てきたことを基にすると、promiseの代わりにコールバックを使用する理由が本当にわかりません。本当?
まず、コールバックと非同期操作の約束を組み合わせたコードを記述することはほとんどありません。 promiseに移行する場合、またはいくつかのpromiseを導入する場合は、おそらくコードの同じセクション内のコールバックをpromiseにリファクタリングする必要があります。適切なタイプの操作については、単純なコールバックよりも多くのpromiseの利点があるため、すでにコードの領域で作業しているときに変換するのに十分な価値があります。
約束は素晴らしい:
pending
、fulfilled
、rejected
の3つの状態のみがあり、pending => fulfilled
またはpending => rejected
からの状態遷移が変更できないPromiseモデルに適合する操作一方向の移行)。プレーンコールバックは、promiseができないことには適しています:
Array.prototype.map()
のコールバックなど)そして、EventEmitter
もミックスに追加します。
EventEmitterは以下に最適です:
プレーンコールバックコードをPromisesに変換する際の注意事項
コールバックが、最後の引数として渡され、このcallback(err, result)
のように呼び出されるコールバックを使用して、ノードの呼び出し規約に適合する場合、ノードでutil.promisify()
を含むプロミスで親関数をいくらか自動的にラップします。 jsまたは Bluebird promise library を使用する場合、 Promise.promisify()
を使用します。
Bluebirdを使用すると、次のような(node.js呼び出し規約で非同期コールバックを使用する)モジュール全体を一度に約束することもできます。
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.writeFileAsync("file.txt", data).then(() => {
// done here
}).catch(err => {
// error here
});
node.jsバージョン8 +
Node.js非同期呼び出し規約を使用する非同期関数を、promiseを返す関数に変換するutil.promisify()
があります。
doc: の例
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
// usage of promisified function
stat('.').then((stats) => {
// Do something with `stats`
}).catch((error) => {
// Handle the error.
});
どちらも同じ問題を解決し、非同期関数の結果を処理するために存在します。
コールバックはより冗長になる傾向があり、複数の非同期リクエストを同時に調整すると、 callback hell につながる可能性があります。関数。エラー処理およびトレースは、コールスタックのさらに1つのエラーにすべて戻る多くのErrorオブジェクトが存在する可能性があるため、それほど簡単ではなく、混乱を招く傾向があります。また、エラーは、コールバックチェーンで匿名関数が使用された場合に元のエラーがスローされた場所を判断するときに頭を傷つける可能性がある、元の呼び出し元に戻す必要があります。コールバックの利点の1つは、単純な古い関数であり、非同期操作がどのように機能するかを知ること以上の追加の理解を必要としないことです。
約束はより少ないコードを必要とするためより一般的であり、同期関数のように書かれ、単一のエラーチャネルを持ち、スローされたエラーを処理でき、 util.promisify()
Node.jsの最新バージョンは、Error-First Callbacksをpromiseに変換できます。 Node.jsへの移行 であるasync/await
もあり、Promiseとのインターフェースもあります。
これは完全に意見に基づいているため、実際に最も快適なものについてですが、Promiseとasync/await
はコールバックの進化であり、非同期開発エクスペリエンスを向上させます。これは、決して徹底的な比較ではなく、コールバックとプロミスの両方の高レベルな見方です。
私はこのようなものをどこから手に入れたか覚えていませんが、約束をよりよく理解するのに役立つかもしれません。
約束はコールバックではありません。 promiseは、非同期操作の将来の結果を表します。もちろん、あなたのやり方でそれらを書いても、ほとんど利益はありません。ただし、使用する方法で記述すれば、同期コードに似た方法で非同期コードを記述でき、より簡単に追跡できます。[〜#〜] advantages [〜#〜] 1.コールバックの読みやすさ2.エラーをキャッチしやすい。 3.同時コールバック
1。コールバックの読みやすさ Promiseは、JavaScriptで順次非同期操作を表現する、より簡潔で明確な方法を提供します。これらは、コールバックと同じ効果を達成するための実質的に異なる構文です。利点は、読みやすさが向上することです。このようなもの
aAsync()
.then(bAsync)
.then(cAsync)
.done(finish);
これらの個々の関数をコールバックとして渡すのと同等の方法よりもはるかに読みやすい
aAsync(function(){
return bAsync(function(){
return cAsync(function(){
finish()
})
})
});
2。エラーをキャッチするのは簡単です。確かに、それほどコードは少なくありませんが、はるかに読みやすくなっています。しかし、これで終わりではありません。真の利点を見つけましょう:いずれかのステップでエラーをチェックしたい場合はどうでしょうか?コールバックでそれを行うのは地獄になりますが、約束では簡単です:
api()
.then(function(result) {
return api2();
})
.then(function(result2){
return api3();
})
.then(function(result3){
// do work
})
.catch(function(error) {
//handle any error that may occur before this point
});
/* Pretty much the same as a try { ... } catch block.
Even better: */
api()
.then(function(result){
return api2(); })
.then(function(result2){
return api3(); })
.then(function(result3){
// do work
})
.catch(function(error) {
//handle any error that may occur before this point
})
.then(function() {
//do something whether there was an error or not
//like hiding an spinner if you were performing an AJAX request.
});
。同時コールバックそしてさらに良い: api、api2、api3へのこれらの3つの呼び出しが同時に実行できた場合(たとえば、AJAX呼び出し)でしたが、約束がなければ、カウンターを作成する必要がありますが、約束では、ES6表記を使用すると、別の簡単できれいなものになります。
Promise.all([api(), api2(), api3()])
.then(function(result) {
//do work. result is an array containing the values of the three fulfilled promises.
})
.catch(function(error) {
//handle the error. At least one of the promises rejected.
});
Promisesが今新しい光で見られることを願っています.