2016-10-04 3 views
0

私は、コールバックまたは約束を持つ実装を持つことができる非同期認証ハンドラを用意しようとしています。スコープは、常に約束を返すためにこの関数をラップすることです、それで、私はそれをさらにコールバック/約束には無関係に使うことができます。常に約束を返すためにcallback/promise実装でjavascript関数を作成する

誰かがこれらのシナリオに助けを与えることができれば、私は最も感謝しています。その例の1つは実生活です。

機能がある場合はどうのようなもの:

function getData(id, callback) { 
    var deferred = Q.defer(); 
    apiCall('/path/to/id', function (err, data) { 
    if (err) deferred.reject(new Error(err)); 
    //do something with data 
    deferred.resolve(processedData); 
    } 
    deferred.promise.nodeify(callback); 
    return deferred.promise; 
} 

と、私はこのよう

function myProcessedDataFunction(id) { 
    return Promise.fromCallback(function (callback) { 
    return getData(id, callback); 
    }, {multiArgs: true}); 
} 

この作品はウィルで.fromCallbackを使いたいですか? myProcessedDataFunctionは正しい約束を返しますか?

現実世界の例は次のとおりです。

私がまたはコールバック関数で実装されていない場合があります、そして同時に約束を使用して実装することができ、認証ハンドラを持っています。真偽値を返す可能性があります。

function authHandlerImplementation1(username, password) { 
    return (username === 'validUsername' && password === 'validPassword'); 
} 

function authHandlerImplementation2(username, password, callback) { 
    apiCall('/path/to/authorization', function (err, result) { 
    if (err) return callback(err, null); 
    callback(null, result); 
    }); 
} 

function authHandlerImplementation3(username, password) { 
    return new Promise(function (reject, resolve) { 
    apiCall('/path/to/authorization', function (err, result) { 
     if (err) return reject(err); 
     resove(result); 
    }); 
    }); 
} 

function authHandlerImplementation4(username, password, callback) { 
    var deferred = Q.defer(); 
    apiCall('/path/to/id', function (err, data) { 
    if (err) deferred.reject(new Error(err)); 
    //do something with data 
    deferred.resolve(processedData); 
    } 
    deferred.promise.nodeify(callback); 
    return deferred.promise; 
} 

私は5番目のブルーバードの実装を試みます。

function authHandlerImplementation5(username, password, callback) { 
    return apiCall('/path/to/id', callback).asCallback(callback); // I hope this is the right way to do it (correct me if I'm wrong, please) 
} 

私のcheckAuth関数はauthHandler実装を使用しており、コールバック/約束には依存したくありません。

function checkAuth(username, password) { 
    var self = this; 
    return Promise.fromCallback(function(callback) { 
    return self.authHandler(username, password, callback); 
    }, {multiArgs: true}); 
} 

場合authHandlerImplementationは(implementation1)、checkAuthのハングは、何も起こりません、私のテストが失敗した(単に値を返す)コールバックを使用していません。

任意の種類のauthHandler実装を約束(単純な戻り値、コールバックまたは約束の実装)にラップすることができるBluebirdメソッドはありますか?

+1

私は、約束とコールバックスタイルの機能を混ぜるのは良い考えではないと思います。私はそれをつけることがずっと良いと思うし、機能をエントリー時の好みのものに変換する。その理由は、関数がコールバックを使用するかどうかを判断することは不可能だからです。 'authHandler'が同期で、即値が未定義を返す場合はどうなりますか?ところで、bluebirdの 'fromCallback'はコールバックスタイル関数でのみ動作します。 –

+2

私はあなたがコールバックか約束を(どちらかというとうまくいけば)選ぶことを強くお勧めします。両方をサポートすることはここでは面倒で、コールサイトでサポートされています。私が働いている男は、両方の方法をサポートしている非常に多くのコードを書いており、メンテナンスの地獄に変わった。これをJust-Promisesの実装に置き換えると、LoCが半分になり、コードをもっと理解しやすくなりました。 – Bojangles

+0

私はあなたの立場を理解しており、簡潔にするために異形の1つに固執することに同意します。反対側では、私はどちらかを使用する自由をエンドユーザに与えたい。実装スタイルを強制しないことは、これで達成しようとしていることです。 @TamasHegedus基本的な質問の1つは、あなたが述べたとおりです。関数がコールバックまたは約束を使用しているのか、それともどちらも使用していないのか、どのように把握できますか? コールバックで実装された関数の '' fromCallback''は '' 'only'''であることが分かりました。私はそれが有望なスタイル機能をサポートしていると思った。 これを行う方法がある場合は、アドバイスをお願いします。 –

答えて

2

いいえ、Bluebirdにはそのようなユーティリティはありません。コールバックとプロビジョニングの両方をサポートすることは、APIを使用する必要があるときではなく、コールバックを返すか、または約束を返すか、または両方を約束するかどうかを外部から判断できない場合や、 (毎回の呼び出しで)可能かもしれないが扱いにくいかもしれません。

ブルーバードは、返却投げたり、それがPromise.methodと呼ばれるの約束を返す可能性がある機能をラップ(と、すぐにそれを呼び出すPromise.tryもあります)ユーティリティを持っています。

非同期の認証ハンドラを渡す場合は、呼び出し元にプロミスを使用させることをお勧めします。コールバックベースのものだけを持っている場合は、利用できるようにする前に自分自身でPromise.promisifyにラップすることもできます。

0

私はいくつかのものを試してみました。以下で試した方法の詳細情報を提供します。このシナリオは、json-rpc 2.0サーバーの実装で、要求内の提供された資格情報の妥当性をチェックするauthHandler関数の実装を受け取ります。

更新:
Promiseの使用。メソッドauthHandler
var promisifiedAuthHandler = Promise.method(self.authHandler);は、authHandlerの同期実装に使用できます。
コールバックの実装に失敗します。

Promise.methodでラップされたauthHandlerでPromise.promisifyを使用すると、コールバック実装のために機能します
var promisifiedAuthHandler = Promise.promisify(Promise.method(self.authHandler));
同期実装に失敗します。

authHandlerのコールバックを(実装で使用しない場合でも)提供することは、すべてのメソッドで機能します。それはこのようになります(一般的なケースのために書いて、これはES5-Class node moduleを使って書かれたモジュールの一部である):

function _checkAuth(req) { 
    var self = this; 
    var credentials = self._getCredentials(req); 
    var promisifiedAuthHandler = Promise.method(self.authHandler); // for the sync implementation 

    switch (authType) { 
    // general case, let's say, there are several types 
    // will just write one as an example. 
    case Authorization.WHATEVERTYPE: 
    return promisifiedAuthHandler(credentials, function callback(err, result) { 
     if (err) return Promise.reject(err); 
     return Promise.resolve(result); 
    } 
    } 
} 

とserver.enableCookie/JWT /にBasicAuthハンドラを挙げる三つの方法で実装することができます:同期/コールバック/約束。次のように:

server.enableCookieAuth(function (cookie) { 
    return (cookie === validCookieValue); 
}); 

server.enableCookieAuth(function (cookie, callback) { 
    apiCall('path/to/auth', function(err, result) { 
    // apiCall could have a promise implementation, as well, and could 
    // be used with .then/.catch, but this is not that important here, since we care 
    // about the handler implementation) 
    if (err) return callback(err, null); 
    callback(null, result); // can be returned 
    } 
}); 

server.enableCookieAuth(function (cookie) { 
    // let's write the apiCall with promise handling, since we mentioned it above 
    return apiCall('path/to/auth').then(function (result) { 
    return Promise.resolve(result); 
    }).catch(function (err) { 
    return Promise.reject(err); 
    }); 
}); 

を今、我々は内部authHandler機能の実装のとらわれないだけの約束を、使用して私たちの_checkAuth機能を使用することができます。次のように:

handleHttp: function(req, res) { 
    var self = this; 
    // ...other processing 
    self._checkAuth(req).then(function (result) { 
    // check if the user is authed or not 
    if (result) { 
     // further process the request 
    } else { 
     // handle unauthorized request 
    } 
    }).catch(function (err) { 
    // handle internal server or api call (or whatever) error 
    }); 
} 

トリックは約束の実装でコールバックを書くことでした。 authHandlerがコールバック実装を使用しない場合でも、authHandlerには常にコールバック実装が提供されます。このようにして、コールバックスタイルの実装を使用する場合、認証ハンドラの実装が約束を返すようにします。

すべてのコメントは歓迎されており、この点についていくつかの意見をお寄せください。

ご連絡ありがとうございます。

関連する問題