19

AJAXおよびHTTPリクエストの非同期性を隠すようにAPIを設計する方法、または基本的にそれを遅らせて流暢なインターフェイスを提供する方法を教えてください。Twitterの新しいAnywhereAPIの例を示すには:

// get @ded's first 20 statuses, filter only the tweets that
// mention photography, and render each into an HTML element
T.User.find('ded').timeline().first(20).filter(filterer).each(function(status) {
    $('div#tweets').append('<p>' + status.text + '</p>');
});

function filterer(status) {
    return status.text.match(/photography/);
}

vsこれ(各呼び出しの非同期性がはっきりと見える)

T.User.find('ded', function(user) {
    user.timeline(function(statuses) {
        statuses.first(20).filter(filterer).each(function(status) {
            $('div#tweets').append('<p>' + status.text + '</p>');
        });
    });
});

function filterer(status) {
    return status.text.match(/photography/);
}

ユーザーを検索し、ツイートのタイムラインを取得し、最初の20件のツイートのみをフィルタリングし、カスタムフィルターを適用し、最終的にコールバック関数を使用して各ツイートを処理します。

このような適切に設計されたAPIは、each / map / etcなどのループ関数に到達するまで、各関数呼び出しがクエリ(この場合はHTTP URL)を構築するクエリビルダー(ORMを考えてください)のように機能するはずです。 HTTP呼び出しが行われ、渡された関数がコールバックになります。

簡単な開発ルートは、各AJAX呼び出しを同期させることですが、それはおそらく最善の解決策ではありません。私はそれを非同期にする方法を考え出し、それでもAJAXの非同期性を隠すことに興味があります。

4

3 に答える 3

20

ほんの数日前に@anywhereのTwitterエンジニアであるDustinDiazによって公開された次の記事をご覧ください。

彼は、非同期メソッド、基本的にはコールバックとは独立してチェーンされたメソッドに、非常に単純なQueue実装を使用して、流暢なインターフェイスを実装できる非常に優れた手法について語っています。

于 2010-05-09T02:24:33.780 に答える
5

私は、もともとCrockford の約束(元のスライド)に基づいていたFutureJSを開発しています。現在の目標は、JavaScript の非同期ツールボックスになり、チェーンの乱雑さをなくすことです。

Futures.chainify(プロバイダー、コンシューマー、コンテキスト、パラメーター)

非同期メソッド キューイングを使用すると、すぐに利用できる場合とそうでない場合があるデータに対して一連のアクションを実行できます。これが、Twitter の @Anywhere API のしくみです。

この方法でデータをリモートでフェッチするモデルが必要になる場合があります。

Contacts.all(params).randomize().limit(10).display();
Contacts.one(id, params).display();

次のように実装できます。

var Contacts = Futures.chainify({
  // Providers must be promisables
  all: function(params) {
    var p = Futures.promise();
    $.ajaxSetup({ error: p.smash });
    $.getJSON('http://graph.facebook.com/me/friends', params, p.fulfill);
    $.ajaxSetup({ error: undefined });
    return p.passable();
  },
  one: function(id, params) {
    var p = Futures.promise();
    $.ajaxSetup({ error: p.smash });
    $.getJSON('http://graph.facebook.com/' + id, params, p.fulfill);
    $.ajaxSetup({ error: undefined });
    return p.passable();
  }
},{
  // Consumers will be called in synchronous order
  // with the `lastResult` of the previous provider or consumer.
  // They should return either lastResult or a promise
  randomize: function(data, params) {
    data.sort(function(){ return Math.round(Math.random())-0.5); // Underscore.js
    return Futures.promise(data); // Promise rename to `immediate`
  },
  limit: function(data, n, params) {
    data = data.first(n);
    return Futures.promise(data);
  },
  display: function(data, params) {
    $('#friend-area').render(directive, data); // jQuery+PURE
    // always return the data, even if you don't modify it!
    // otherwise your results could be unexpected
    return data;
  }
});

知っておくべきこと:

  • providers- データを返すpromisables
  • consumers- データを使用または変更する関数
    • 最初の引数はdata
    • Promisable を返す場合、チェーン内の次のメソッドは Promise が満たされるまで実行されません。
    • 「リテラルオブジェクト」を返すとき、チェーンの次のメソッドはそのオブジェクトを使用します
    • 返すundefined(または何も返さない) 場合、チェーン内の次のメソッドは定義されたオブジェクトを使用します
  • context-apply()各プロバイダーとコンシューマーに d を送信し、thisオブジェクトになる
  • params- 将来の使用のために予約

別の方法として、同期コールバック チェーンを使用することもできます。これは、別の場所で chain().next() または then() として見られたものです。

Futures.sequence(function(callback) {

    $.getJSON("http://example.com", {}, callback);

}).then(function(callback, result, i, arr) {

    var data = transform_result(result);
    $.getJSON("http://example.com", data, callback);

}).then(...)

sequence_.jschainには既に名前の付いたメソッドがchainあり、ライブラリにも _.methodName を使用したいので、名前を付けました。

のぞいて、あなたの考えを教えてください

FuturesJS は、jQuery、Dojo などと一緒に問題なく動作します。依存関係はありません。Node.js (および env.js を使用する場合は Rhino) で動作します。

=8^D

PS ORM/MVC の修正に関しては、JavaScriptMVCSproutCoreを確認できます。TriforceJS という独自のソリューションにも取り組んでいますが、まだリリースできるものはありません。

PPSの例promisables

var doStuff = function (httpResult) {
    // do stuff
  },
  doMoreStuff = function (httpResult) {
    // do more stuff
  };

function fetchRemoteData(params) {
  var promise = Futures.promise();
  $.getJSON("www.example.com", params, promise.fulfill, 'jsonp');
  return promise;
}

p = fetchRemoteData(params);
p.when(doStuff);
p.when(doMoreStuff);
于 2010-07-14T23:05:03.987 に答える
0

AJAX 同期の問題は、jQuery などのライブラリ (つまり、 asyncプロパティを介して非同期または同期操作を指定できるajax 呼び出し) によって既に抽象化されていると思います。同期モードを選択すると、実装の非同期性が隠されます。

jQuery も流暢なインターフェースとチェーンの例です。同じことを行う他のライブラリがあります。車輪を再発明する手間を省きます - 探しているものをすぐに手に入れることができます。

これが答えとして機能する場合、これらの機能間でブラウザの自動互換性が良好になります。そのようなものは、ゼロから構築するのに長い時間がかかります.

Twitter の新しい Anywhere API ノート jQuery が表示されます。掘り下げれば、すべてが既に存在する可能性があります。

于 2010-05-09T02:42:57.857 に答える