Skip to content

Instantly share code, notes, and snippets.

@Leko
Last active August 29, 2015 14:17
Show Gist options
  • Save Leko/77bbe45a1768608b4608 to your computer and use it in GitHub Desktop.
Save Leko/77bbe45a1768608b4608 to your computer and use it in GitHub Desktop.
Backbone.jsのModelとCollectionで最大接続数を絞ってAjaxリクエストするスニペット。listenしてるイベント名やコールバックの反応のさせ方を変えれば他のライブラリにも適応可能かと。
var SomeCollection = Backbone.Collection.extend({
/**
* 同時リクエスト数を制限したリクエストを行う
*
* RESTに寄せて1個1個のモデルを更新する場合、一気に大量のAjaxが走ることになる。
* サーバ側の不可を考慮し、同時リクエスト数を絞ったAjaxリクエストを行う。
*
* 最初に同時リクエスト数分のリクエストを作成し、その後は1個1個の通信が完了するたびに1つずつ次の通信へ移る。
*
* 各モデルの保存が完了するごとに...といった処理は事前にイベントリスナを定義しておくこと。
* 各モデルの保存処理が完了した際のコールバックは提供しない。
*
* @param Backbone.Model[] models 保存を行うモデルの一覧
* @param int maxConnection 同時リクエストを許可する最大数。デフォルトは10
* @param string method モデルに対して行う操作
* @param mixed args... モデルに対して行う操作に渡す引数
* @return $.Deferred 全ての保存が完了/失敗したときにresolveされる
*/
throttleRequest: function(models, maxConnection, method/*, args... */) {
maxConnection = maxConnection || SomeCollection.MAX_CONNECTION;
method = method || 'save';
function next() {
if(models.length === 0) {
promise.resolve();
return;
}
// NOTE: 無名関数だとこのコールバックだけを解除出来ないので名前付き関数化している
function callback() {
_this.stopListening(model, 'sync', callback);
_this.stopListening(model, 'error', callback);
next();
}
var model = models.splice(0, 1)[0];
_this.listenToOnce(model, 'sync error', callback);
model[method].apply(model, args);
}
var _this = this,
args = _.rest(arguments, 3),
promise = $.Deferred();
for(var i = 0; i < maxConnection; i++) next();
return promise;
}
}, {
MAX_CONNECTION: 10
});
var collection = new SomeCollection(),
models = [];
for(var i = 1; i <= 50; i++) {
models.push(new Backbone.Model({ hoge: i }));
}
collection.throttleRequest(models);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment