Dynamics CRM REST/ODATA Web サービス (CrmRestKit)用の小さなライブラリを開発しました。lib は jQuery に依存し、jQuery の promise-like-pattern である promise-pattern を利用します。
今、私はこのライブラリをbluebirdに移植し、jQuery の依存関係を削除したいと考えています。しかし、bluebird は promise オブジェクトの同期解決をサポートしていないため、問題に直面しています。
いくつかのコンテキスト情報:
CrmRestKit の API は、Web サービス呼び出しを同期モードまたは非同期モードで実行する必要があるかどうかを定義するオプションのパラメーターを除きます。
CrmRestKit.Create( 'Account', { Name: "foobar" }, false ).then( function ( data ) {
....
} );
「true」を渡すか、最後のパラメーターを省略すると、メソッドはレコードを同期して作成します。モード。
場合によっては、同期モードで操作を実行する必要があります。たとえば、フォームの保存イベントに関与する Dynamics CRM の JavaScript コードを記述し、このイベント ハンドラーで検証のために同期操作を実行する必要があります (たとえば、特定の数の子レコードが存在することを検証し、適切な数のレコードが存在する場合は、保存操作をキャンセルしてエラー メッセージを表示します)。
私の問題は次のとおりです。bluebird は同期モードでの解像度をサポートしていません。たとえば、次のようにすると、「then」ハンドラーが非同期で呼び出されます。
function print( text ){
console.log( 'print -> %s', text );
return text;
}
///
/// 'Promise.cast' cast the given value to a trusted promise.
///
function getSomeTextSimpleCast( opt_text ){
var text = opt_text || 'Some fancy text-value';
return Promise.cast( text );
}
getSomeTextSimpleCast('first').then(print);
print('second');
出力は次のとおりです。
print -> second
print -> first
promise は既に値で解決されているため、「second」は「first」の後に表示されると予想されます。したがって、既に解決された promise-object に適用されると、 then-event-handler がすぐに呼び出されると想定します。
jQuery を使用して同じことを行うと (既に解決されたプロミスで使用)、期待どおりの結果が得られます。
function jQueryResolved( opt_text ){
var text = opt_text || 'jQuery-Test Value',
dfd = new $.Deferred();
dfd.resolve(text);
// return an already resolved promise
return dfd.promise();
}
jQueryResolved('third').then(print);
print('fourth');
これにより、次の出力が生成されます。
print -> third
print -> fourth
ブルーバードを同じように機能させる方法はありますか?
更新: 提供されたコードは、問題を説明するためのものです。lib の考え方は次のとおりです。実行モード (同期、非同期) に関係なく、呼び出し元は常に promise オブジェクトを処理します。
「... ユーザーに尋ねる...意味がないようです」について: 「CreateAsync」と「CreateSync」の 2 つのメソッドを提供する場合、操作の実行方法を決定するのもユーザー次第です。
とにかく、現在の実装では、デフォルトの動作 (最後のパラメーターはオプション) は非同期実行です。したがって、コードの 99% は promise-object を必要とします。オプションのパラメーターは、単に同期実行が必要な 1% のケースでのみ使用されます。さらに、私は自分で lib を開発し、99,9999% のケースで async モードを使用していますが、必要に応じて sync-road に移動するオプションがあると便利だと思いました。
しかし、同期メソッドは単に値を返す必要があるという点は理解できたと思います。次のリリース (3.0) では、「CreateSync」と「CreateAsync」を実装します。
ご意見ありがとうございます。
Update-2 オプションのパラメーターの意図は、一貫した動作を保証し、論理エラーを防ぐことでした。libを使用する私の方法「GetCurrentUserRoles」の消費者としてあなたを想定してください。したがって、メソッドは常にプロミスを返します。つまり、結果に依存するコードを実行するには、「then」メソッドを使用する必要があります。したがって、一部の人がこのようなコードを書くとき、私はそれが完全に間違っていることに同意します:
var currentUserRoels = null;
GetCurrentUserRoles().then(function(roles){
currentUserRoels = roles;
});
if( currentUserRoels.indexOf('foobar') === -1 ){
// ...
}
メソッド「GetCurrentUserRoles」が同期から非同期に変更されると、このコードが壊れることに同意します。
しかし、これは良い設計ではないことは理解しています。なぜなら、消費者は非同期メソッドを扱う必要があるからです。