Javascript 从第三方API填充模型

Javascript 从第三方API填充模型,javascript,backbone.js,backbone-views,backbone.js-collections,Javascript,Backbone.js,Backbone Views,Backbone.js Collections,我正在为一个个人项目使用主干网,在这个项目中,我创建了一个名为MyModel的模型。在初始化此模型时,我想从第三方API的JSON响应中填充其属性: app.MyModel = Backbone.Model.extend({ url: 'https://api.xxxxxx.com/v12_1/item?id=53444d0d7ba4ca15456f5690&appId=xxxx&appKey=yyyy', defaults: { n

我正在为一个个人项目使用主干网,在这个项目中,我创建了一个名为
MyModel
的模型。在初始化此模型时,我想从第三方API的JSON响应中填充其属性:

app.MyModel = Backbone.Model.extend({
      url: 'https://api.xxxxxx.com/v12_1/item?id=53444d0d7ba4ca15456f5690&appId=xxxx&appKey=yyyy',

      defaults: {
          name: 'Default Name'
      }

  });
此模型用于将在另一个模型中嵌入的属性中使用的集合:

app.MyModels = Backbone.Collection.extend({
    model: app.MyModel
});

app.MyModel2 = Backbone.Model.extend({

    // Default attributes
    defaults: {
        name: 'Default Name'
    },

    initialize: function() {
        this.myModels = new app.MyModels();
        this.myModels.on('change', this.save);
    }
});
在为
MyModel2
创建的视图中,我向全局元素添加了一个侦听器,这样我们就可以初始化
MyModel
并将
MyModels
的实例添加到
MyModel2
内部

app.MyModel2View = Backbone.View.extend({

    initialize: function() {
        // ...some code...
        var self = this;
        this.$(".add-myModel").click(function() {
            var myModel = new app.MyModel();
            myModel.fetch();
            self.model.myModels.add(myModel);
        });
        // ...some code...
    },
    // ...some code...
});
这实际上实现了预期目标,但在单击元素并添加实例时,控制台中会抛出一个错误:

backbone.js:646 Uncaught TypeError: this.isNew is not a function

在主干网中,这是从外部API填充模型实例的正确方法吗?我正在试图找出此错误的原因。

如果没有更完整的信息,很难说,但在保存
MyModels
时,您似乎没有正确设置上下文:

this.myModels.on('change', this.save);
这是
on()
方法的最后一个可选参数,因此可能:

this.myModels.on('change', this.save, this);
请参阅

中的详细信息,而他只关注最可能出现的错误,而让您处理所有其他问题。我将在我的回答中对此进行详细阐述


查询字符串中ID为的模型URL API的URL非常复杂,每次需要时复制粘贴都很麻烦。最好在一个地方处理URL,实现这一点的一种方法是使用简单的服务

用API信息填充它

然后,可以创建基础模型和集合(或替换默认主干行为)

那么使用它就这么简单:

app.MyModel = app.BaseModel.extend({
    urlRoot: app.API.url('item'),
})

app.Collection = app.BaseCollection.extend({
    model: app.MyModel,
    url: app.API.url('collection-items'),
});
以下测试输出:

var-app=app | |{};
(功能(){
app.API={
协议:“https”,
域:“api.xxxxxx.com”,
根目录:'/v12_1/',
参数:{
appId:'xxxx',
appKey:'yyy',
},
/**
*获取完整的API url以及可选路径。
*@param{String}路径(可选)以添加到url。
*@return{String}包含协议、域、根的完整API url。
*/
url:函数(路径){
路径=路径| |“”;
如果(path.slice(-1)!='/')路径+='/';
返回this.protocol+“:/”+this.domain+this.root+路径;
},
/**
*将查询字符串添加到url,并与默认API参数合并。
*查询字符串前的@param{String}url(可选)
*@param{Object}params转换为查询字符串
*@return{String}例如:“你的url?param=value&otherparam=123”
*/
applyParams:函数(url、参数){
返回(url | |“”)+“?”+$.param({}.extend({},this.params,params));
},
};
app.BaseModel=Backbone.Model.extend({
setId:函数(id,选项){
返回this.set(this.idAttribute,id,options);
},
url:function(){
var基=
_.result(此“urlRoot”)||
_.result(此.collection为“url”)||
urlError();
var id=this.get(this.idAttribute);
返回app.API.applyParams(base,this.isNew(){
id:encodeURIComponent(id)
});
},
});
app.BaseCollection=Backbone.Collection.extend({
型号:app.BaseModel,
同步:函数(方法、集合、选项){
var url=options.url | | | | |结果(模型,'url')| | urlError();
options.url=aop.API.applyParams(url);
返回app.BaseCollection.super.sync.apply(这是参数);
}
});
app.MyModel=app.BaseModel.extend({
urlRoot:app.API.url('item'),
})
app.Collection=app.BaseCollection.extend({
型号:app.MyModel,
url:app.API.url('collection-items'),
});
var model=new app.MyModel();
log(“新模型url:,model.url());
型号setId(“53444d0d7ba4ca15456f5690”);
log(“现有模型url:,model.url());
var collection=新建app.collection();
log(“集合url:,”结果(集合,'url');
var modelUrlThroughCollection=新建app.BaseModel({
id:“test1234”
});
collection.add(modelUrlThroughCollection);
log(“通过集合建模:”,modelUrlThroughCollection.url());
})();

虽然我尽了最大努力,但如果您添加一个API响应示例和其他可用端点,这将非常有帮助。此外,您应该真正地使用有意义的名称,即使它只是一个示例,例如
MyModel
MyModels
MyModel2
MyModel2View
都不是描述性名称。
app.BaseModel = Backbone.Model.extend({
    setId: function(id, options) {
        return this.set(this.idAttribute, id, options);
    },
    url: function() {
        var base =
            _.result(this, 'urlRoot') ||
            _.result(this.collection, 'url') ||
            urlError();
        var id = this.get(this.idAttribute);
        return app.API.applyParams(base, this.isNew() || { id: encodeURIComponent(id) });
    },
});

app.BaseCollection = Backbone.Collection.extend({
    model: app.BaseModel,
    sync: function(method, collection, options) {
        var url = options.url || _.result(model, 'url') || urlError();
        options.url = aop.API.applyParams(url);
        return app.BaseCollection.__super__.sync.apply(this, arguments);
    }
});
app.MyModel = app.BaseModel.extend({
    urlRoot: app.API.url('item'),
})

app.Collection = app.BaseCollection.extend({
    model: app.MyModel,
    url: app.API.url('collection-items'),
});