Backbone.js를 사용하여 수집 폴링
Backbone.js Collection을 서버에서 발생하는 상황을 최신 상태로 유지하려고 합니다.
내 코드는 다음과 유사합니다.
var Comment = Backbone.Model.extend({});
var CommentCollection = Backbone.Collection.extend({
model: Comment
});
var CommentView = Backbone.View.extend({ /* ... */ });
var CommentListView = Backbone.View.extend({
initialize: function () {
_.bindAll(this, 'addOne', 'addAll');
this.collection.bind('add', this.addOne);
this.collection.bind('refresh', this.addAll);
},
addOne: function (item) {
var view = new CommentView({model: item});
$(this.el).append(view.render().el);
},
addAll: function () {
this.collection.each(this.addOne);
}
});
var comments = new CommentCollection;
setInterval(function () {
comments.fetch();
}, 5000);
무슨 일이 일어나냐면 댓글을 가져오면refresh
호출되며, 아래에 있는 동일한 주석CommentListView
--이것이 바로 위의 코드에서 제가 기대했던 것입니다.
제가 알고 싶은 것은 "로컬 상태"를 잃지 않고 뷰를 "새로 고치는" 가장 좋은 방법이 무엇인지 알고 싶습니다.
또는 백본의 가져오기 방법에 훨씬 더 간단한 추가 기능을 사용하십시오.
this.fetch({ update: true });
모델 데이터가 서버에서 반환되면 {update:true}을(를) 통과하지 않는 한 컬렉션이 (효율적으로) 재설정됩니다. 이 경우 업데이트를 사용하여 가져온 모델을 (지능적으로) 병합합니다. - Backbone Documentation
:-)
몇 초마다 컬렉션을 새로 고치고 새 주석을 추가합니다.제 제안은 당신의 백엔드에서 그 문제를 처리하는 것입니다.마지막 주석의 마지막 타임스탬프를 전송하고 서버에 이 날짜 이후의 델타만 요청합니다.
이렇게 하려면 컬렉션에서 다음을 수행합니다.
CommentCollection = Backbone.Collection.extend({
url: function(){
return "/comments?from_time=" + this.last().get("created_at");
},
comparator: function(comment){
return comment.get("created_at");
}
});
백엔드에서 from_time 매개 변수를 기준으로 데이터베이스를 쿼리합니다.보기를 새로 고치기 위해 클라이언트 코드는 변경되지 않습니다.
어떤 이유로든 백엔드 코드를 변경하지 않으려면 addAll 함수에 다음 행을 추가합니다.
addAll: function(){
$(this.el).empty();
this.collection.each(this.addOne);
}
등뼈.Collection.merge([옵션])
위의 @Jeb의 응답을 바탕으로, 저는 이 동작을 백본 확장자로 캡슐화했습니다. 이것은 당신이 복사해서 .js 파일로 붙여 당신의 페이지에 포함시킬 수 있습니다(백본 라이브러리 자체를 포함한 후).
다음과 같은 방법을 제공합니다.merge
등뼈를 위하여.컬렉션 개체입니다.기존 컬렉션을 완전히 재설정하는 대신fetch
서버 응답을 기존 컬렉션과 비교하고 차이점을 병합합니다.
- 반응에는 있지만 기존 집합에는 없는 모형을 추가합니다.
- 기존 집합에는 있지만 반응에는 없는 모형을 제거합니다.
- 마지막으로, 기존 컬렉션과 응답에서 발견된 모델의 속성을 업데이트합니다.
모델을 추가, 제거 및 업데이트할 때 예상되는 모든 이벤트가 트리거됩니다.
해시에 필요한 옵션success
그리고.error
될 (collection, response)
세인 인로수, 그고그세번째다제니공옵합션을 제공합니다.complete
성공 또는 오류에 관계없이 실행됩니다(폴링 시나리오에 매우 유용함).
"merge:success" 및 "merge:error"라는 이벤트를 트리거합니다.
확장자는 다음과 같습니다.
// Backbone Collection Extensions
// ---------------
// Extend the Collection type with a "merge" method to update a collection
// of models without doing a full reset.
Backbone.Collection.prototype.merge = function(callbacks) {
// Make a new collection of the type of the parameter
// collection.
var me = this;
var newCollection = new me.constructor(me.models, me.options);
this.success = function() { };
this.error = function() { };
this.complete = function() { };
// Set up any callbacks that were provided
if(callbacks != undefined) {
if(callbacks.success != undefined) {
me.success = callbacks.success;
}
if(callbacks.error != undefined) {
me.error = callbacks.error;
}
if(callbacks.complete != undefined) {
me.complete = callbacks.complete;
}
}
// Assign it the model and url of collection.
newCollection.url = me.url;
newCollection.model = me.model;
// Call fetch on the new collection.
return newCollection.fetch({
success: function(model, response) {
// Calc the deltas between the new and original collections.
var modelIds = me.getIdsOfModels(me.models);
var newModelIds = me.getIdsOfModels(newCollection.models);
// If an activity is found in the new collection that isn't in
// the existing one, then add it to the existing collection.
_(newCollection.models).each(function(activity) {
if (_.indexOf(modelIds, activity.id) == -1) {
me.add(activity);
}
}, me);
// If an activity in the existing collection isn't found in the
// new one, remove it from the existing collection.
var modelsToBeRemoved = new Array();
_(me.models).each(function(activity) {
if (_.indexOf(newModelIds, activity.id) == -1) {
modelsToBeRemoved.push(activity);
}
}, me);
if(modelsToBeRemoved.length > 0) {
for(var i in modelsToBeRemoved) {
me.remove(modelsToBeRemoved[i]);
}
}
// If an activity in the existing collection is found in the
// new one, update the existing collection.
_(me.models).each(function(activity) {
if (_.indexOf(newModelIds, activity.id) != -1) {
activity.set(newCollection.get(activity.id));
}
}, me);
me.trigger("merge:success");
me.success(model, response);
me.complete();
},
error: function(model, response) {
me.trigger("merge:error");
me.error(model, response);
me.complete();
}
});
};
Backbone.Collection.prototype.getIdsOfModels = function(models) {
return _(models).map(function(model) { return model.id; });
};
단순 사용 시나리오:
var MyCollection = Backbone.Collection.extend({
...
});
var collection = new MyCollection();
collection.merge();
사용 시나리오 처리 오류:
var MyCollection = Backbone.Collection.extend({
...
});
var collection = new MyCollection();
var jqXHR = collection.merge({
success: function(model, response) {
console.log("Merge succeeded...");
},
error: function(model, response) {
console.log("Merge failed...");
handleError(response);
},
complete: function() {
console.log("Merge attempt complete...");
}
});
function handleError(jqXHR) {
console.log(jqXHR.statusText);
// Direct the user to the login page if the session expires
if(jqXHR.statusText == 'Unauthorized') {
window.location.href = "/login";
}
};
중복 컬렉션을 만듭니다.가져오너라.델타를 찾기 위해 두 가지를 비교합니다.발라주세요.
/*
* Update a collection using the changes from previous fetch,
* but without actually performing a fetch on the target
* collection.
*/
updateUsingDeltas: function(collection) {
// Make a new collection of the type of the parameter
// collection.
var newCollection = new collection.constructor();
// Assign it the model and url of collection.
newCollection.url = collection.url;
newCollection.model = collection.model;
// Call fetch on the new collection.
var that = this;
newCollection.fetch({
success: function() {
// Calc the deltas between the new and original collections.
var modelIds = that.getIdsOfModels(collection.models);
var newModelIds = that.getIdsOfModels(newCollection.models);
// If an activity is found in the new collection that isn't in
// the existing one, then add it to the existing collection.
_(newCollection.models).each(function(activity) {
if (modelIds.indexOf(activity.id) == -1) {
collection.add(activity);
}
}, that);
// If an activity in the existing colleciton isn't found in the
// new one, remove it from the existing collection.
_(collection.models).each(function(activity) {
if (newModelIds.indexOf(activity.id) == -1) {
collection.remove(activity);
}
}, that);
// TODO compare the models that are found in both collections,
// but have changed. Maybe just jsonify them and string or md5
// compare.
}
});
},
getIdsOfModels: function(models) {
return _(models).map(function(model) { return model.id; });
},
언급URL : https://stackoverflow.com/questions/5963324/polling-a-collection-with-backbone-js
'IT' 카테고리의 다른 글
PHP와 Ajax를 사용하여 배열을 Javascript로 전달하는 방법은 무엇입니까? (0) | 2023.08.21 |
---|---|
두 NSDate 비교 및 시간 성분 무시 (0) | 2023.08.21 |
ASP.NET 윈도우즈 인증 로그아웃 (0) | 2023.08.21 |
Powershell을 통해 Windows 기능을 활성화하는 방법 (0) | 2023.08.21 |
결과 쿼리에서 개수(*) 선택 (0) | 2023.08.21 |