何の利益の約束を抽象化にCommonJS?
-
23-09-2019 - |
質問
いくつかについて触れたいと思い この記事 とをお約束抽象化るようになることは、少し複雑化します。のとして与えられたとえば:
requestSomeData("http://example.com/foo") // returns a promise for the response
.then(function(response){ // ‘then’ is used to provide a promise handler
return JSON.parse(response.body); // parse the body
}) // returns a promise for the parsed body
.then(function(data){
return data.price; // get the price
}) // returns a promise for the price
.then(function(price){ // print out the price when it is fulfilled
print("The price is " + price);
});
そのため以下のようにも同様の結果では少数のコード:
requestSomeData("http://example.com/foo")
.requestHandler(function(response){
// parse the body
var data = JSON.parse(response.body);
// get the price
var price = data.price;
// print out the price
print("The price is " + price);
});
解決
は、違いはあなたの2番目の例では、非同期ではないということです。例えば、JSON.parse(...)
は非常に高価な操作であることが判明した場合、何が起こるかを検討。あなたはいつもあなたが望むものではない可能性があるすべての完成まで、ハングアップする必要があります。
それは約束はあなたを得るものです。名前が示すように、構築物「の約束は、」今だけとは限らない、いくつかの点であなたの結果を得ました。あなたはここでの より大きな規模での先物と約束の仕事についてもっと読むことができますする の。
他のヒント
のは、純粋なJavaScriptの例に約束の例を比較してみましょう。
// First we need a convenience function for W3C's fiddly XMLHttpRequest.
// It works a little differently from the promise framework. Instead of
// returning a promise to which we can attach a handler later with .then(),
// the function accepts the handler function as an argument named 'callback'.
function requestSomeDataAndCall(url, callback) {
var req = new XMLHttpRequest();
req.onreadystatechange = resHandler;
req.open("GET", url, false);
req.send();
function resHandler() {
if (this.readyState==4 && this.status==200) {
callback(this);
} else {
// todo: Handle error.
}
}
}
requestSomeDataAndCall("http://example.com/foo", function(res){
setTimeout(function(){
var data = JSON.parse(res.responseText);
setTimeout(function(){
var price = data.price;
setTimeout(function(){
print("The price is "+price);
},10);
},10);
},10);
});
ノルベルトHARTLが指摘、JSON.parse()は、大きな文字列をブラウザがハングします。 (10ミリ秒の一時停止後に)その実行を遅らせるためのsetTimeout()を使用私はそう。これはクリスコワルのソリューションの一例です。なお、本DOMの変更にブラウザを解放、完全に現在のJavascriptのスレッドを可能にし、コールバックの実行前に、ユーザーのためにページをスクロールします。
私は恐れていたとして、それ以外の記事の例では、後に約束が実際に同期的に実行されます、commonjsは、フレームワークはまたのsetTimeoutのようなものを使用しています約束を願っています。
さらにインデントを必要とする後工程と、かなり醜いルックス上記私の選択肢。私たちは、すべての1つのレベルで私たちのプロセスチェーンを提供できるように、コードを再構築します:
function makeResolver(chain) {
function climbChain(input) {
var fn = chain.shift(); // This particular implementation
setTimeout(function(){ // alters the chain array.
var output = fn(input);
if (chain.length>0) {
climbChain(output);
}
},10);
}
return climbChain;
}
var processChain = [
function(response){
return JSON.parse(response.body);
},
function(data){
return data.price; // get the price
},
function(price){
print("The price is " + price);
}
];
var climber = makeResolver(promiseChain);
requestSomeDataAndCall("http://example.com/foo", climber);
私は、伝統的な前方パッシングコールバックのJavaScriptでの約束とほとんど同等であることを証明するために期待していました。しかし、2回の試行の後、私は約束ははるかにエレガントな解決策であることを、元の例では、コードの清楚を参照して、示されたように見える!
二スニペットは、サービス拒否攻撃に対して脆弱です。でも、空の応答が無効JSON(有効なJSが)です。これは、SQLインジェクション穴を睨んでmysql_*
の例のようなものです。
そして約束のコードも同様に大幅に改善することができます。これらは等しくます:
requestSomeData("http://example.com/foo") // returns a promise for the response
.then(function(response){ // ‘then’ is used to provide a promise handler
// parse the body
var data = JSON.parse(response.body);
// get the price
var price = data.price;
// print out the price
print("The price is " + price);
});
と
requestSomeData("http://example.com/foo")
.requestHandler(function(response){
try {
var data = JSON.parse(response.body);
}
catch(e) {
return;
}
// get the price
var price = data.price;
// print out the price
print("The price is " + price);
});
私たちがエラーを処理したい場合、これらは等しくなります:
requestSomeData("http://example.com/foo") // returns a promise for the response
.then(function(response){ // ‘then’ is used to provide a promise handler
// parse the body
var data = JSON.parse(response.body);
// get the price
var price = data.price;
// print out the price
print("The price is " + price);
}).catch(SyntaxError, function(e) {
console.error(e);
});
と
requestSomeData("http://example.com/foo")
.requestHandler(function(response){
try {
var data = JSON.parse(response.body);
}
catch(e) {
//If the above had a typo like `respons.body`
//then without this check the ReferenceError would be swallowed
//so this check is kept to have as close equality as possible with
//the promise code
if(e instanceof SyntaxError) {
console.error(e);
return;
}
else {
throw e;
}
}
// get the price
var price = data.price;
// print out the price
print("The price is " + price);
});