IT

Backbone.js를 사용하여 수집 폴링

itgroup 2023. 8. 21. 21:06
반응형

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서버 응답을 기존 컬렉션과 비교하고 차이점을 병합합니다.

  1. 반응에는 있지만 기존 집합에는 없는 모형을 추가합니다.
  2. 기존 집합에는 있지만 반응에는 없는 모형을 제거합니다.
  3. 마지막으로, 기존 컬렉션과 응답에서 발견된 모델의 속성을 업데이트합니다.

모델을 추가, 제거 및 업데이트할 때 예상되는 모든 이벤트가 트리거됩니다.

해시에 필요한 옵션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

반응형