Meteor: 同期ライブラリの使用 - wrapAsync と bindEnvironment
###Meteor.wrapAsyncとMeteor.bindEnvironmentって何?
パート1では、MeteorがFibersを使って非同期コードを抽象化し、同期スタイルでJSを書くための簡単な方法を提供していることを見ました。パート2では、純粋な非同期ライブラリをどのように扱うかを理解します。
Fibersを使えば、非同期関数を修正して同期的なコードを書くことができます。しかし、サードパーティのライブラリのように、関数を変更できない場合はどうなるでしょうか。
ShareThis 、私たちのMeteorアプリケーションは、キャッシュとデータストレージ層としてAmazonのS3を使用しています。Amazon S3のドキュメントによると、S3バケットに追加するJavaScriptのメソッドシグネチャは以下のようになります。
“`
getObject(params = {}, callback) ⇒ AWS.Request
//This is how the function would look in Meteor server code
S3.putObject({
バケットです。'sharethis-insights-store',
Key : キー。
本体:データ
}, function(err, result){.
if(result){
console.log("Done");
//optionally pass in callback
}
});
“`
S3.putObjectのコールバックが現在のFiberにバインドされていないため、上記のコードは期待通りに動作しません。
この使用例では、Meteor.wrapAsyncを使用して、非同期関数を現在のFiberにラップしています。
###Meteor.wrapAsyncは何をするの?
Meteor.wrapAsyncは、最初のパラメータとして与えられたメソッドを取り込み、現在のファイバー内で実行します。
また、コールバックを添付しています(コールバックを使用する伝統的なノードスタイルを想定しています。つまり、メソッドはコールバックを最後のパラメータとして受け取り、2つの引数(errorとresult)を取りますが、呼び出しの結果に応じてどちらかがnullになります。
コールバックはMeteor.bindEnvironmentでバインドされ、コールバックが起動するまで現在のFiberをブロックします。コールバックが実行されるとすぐに、結果を返すか、エラーを投げます。
"`javascript
function synchronousFunc(){
return Meteor.wrapAsync(asyncFunction)
}
“`
**Meteor.wrapAsyncで返される同期ラッピング関数を使って、エラーオブジェクトにアクセスするにはどうすればよいのでしょうか?
一つの方法は、トライ/キャッチブロックを使用することです。エラーが発生した場合、非同期関数のコールバックの第一引数として渡されるのではなく、同期関数によってスローされます。
”`
try{
var result=synchronousFunc(params);
console.log("Success :",result);
}
catch(error){。
console.log("Error:",error);
}
// which is equivalent to –
asyncFunction(params,function(error,result){)
if(エラー)
console.log("error",error);
その他
console.log("result :",result);
});
“`
これは非同期コードを同期コードに変換するのに適しています。コールバックやより深い関数のネストを使用する代わりに、次の行でメソッドの結果を使用することができます。また、コールバックを現在のFiberにバインドする処理(Meteor.bindEnvironmentを使用)も行われます。
最後の注意点として、もし非同期ライブラリ関数のコールバックに何かをさせたい場合(ただ単に)、Meteor.bindEnvironmentを明示的に使用しないと、Meteorのコードは常にFiber内で実行されなければならないというエラーが発生してしまいます。
”`
var func = function(cb){.
S3.putObject(params, Meteor.bindEnvironment(function(err, data) {?
if (err){
throw new Meteor.Error("Storage on S3 Failed");
} else{
console.log("Successfully stored data on S3")と表示されます。
cb(null, data)です。
}
}));
};
return (Meteor.wrapAsync(func))();
“`
Meteor.wrapAsyncを使用する際に注意しなければならないことがあります。
これは、errorとresultを引数に持つコールバックを期待する純粋な非同期関数で動作することを意図しています。また、これらはサーバーサイドでのみ動作します(クライアントサイドではFibersを使用できないため)。
Meteor.HTTP.callのようなサーバーサイドのメソッドは、すでにこのようにラップされています。コールバックなしで呼び出した場合、メソッドはレスポンスを受信するまでブロックします。そうでなければ、すぐに戻り、ネットワーク応答を受信したらコールバックを実行します。