Backbone 模型:Ajax 请求在解析覆盖中
Backbone Model : Ajax request in parse override
我有一个场景,模型的 fetch()
调用将 return 数据,属性 需要从中传递给另一个 API 和 return 中的类型 API 将是实际需要的数据。
var Issue = Backbone.Model.extend({
urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues',
parse: function(response, options){
var markdown = new Markdown({ text : response.body });
markdown.fetch({
contentType: 'application/json',
type: 'POST',
data: JSON.stringify( markdown.toJSON() ),
success: function(data){
response.body = data;
}
});
return response;
}
});
var Markdown = Backbone.Model.extend({
defaults:{
'text': '',
'mode' : 'markdown'
},
url: 'https://api.github.com/markdown'
});
因此,当 Issue
将被提取时:
var issue = new Issue({id: 1});
issue.fetch().then(function(){
//do stuff
});
它将有一个 body
的 属性 包含 markdown 语法文本,我需要将其传递给另一个 API 并获得将传递给查看的响应.
从上面可以看出,我尝试重写 parse
但它的 return 类型必须是一个对象, fetch
将是 async
那么我该怎么办在这里做这项工作?
注意:我知道在服务器中聚合数据然后接收它是最好的主意,但这在 atm 是不可能的。
我认为您必须覆盖模型的 fetch
才能使其正常工作
考虑一下默认提取的样子:
fetch: function(options) {
options = _.extend({parse: true}, options);
var model = this;
var success = options.success;
options.success = function(resp) {
var serverAttrs = options.parse ? model.parse(resp, options) : resp;
if (!model.set(serverAttrs, options)) return false;
if (success) success.call(options.context, model, resp, options);
model.trigger('sync', model, resp, options);
};
wrapError(this, options);
return this.sync('read', this, options);
},
(github)
该实现不支持 model.parse
的异步版本,但由于您使用 .extend
创建模型 class,您可以用自己的实现覆盖它,所以让我们看看确实如此。它需要一个 options
对象,创建一个 success
回调,然后委托给 Backbone.Sync
.
正是那个调用 parse
的回调,这就是支持异步所需要的。
最快、最肮脏的方法可能就是复制和修改现有的默认提取。
var MyModel = Backbone.Model.extend({
fetch: function(options) {
options = _.extend({parse: true}, options);
var model = this;
var success = options.success;
options.success = function(resp) {
function parser(resp, options, cb) {
...do your async request stuff and call cb with the result when done...
}
parser(resp, options, function(result) {
if (!model.set(result, options)) return false;
if (success) success.call(options.context, model, resp, options);
model.trigger('sync', model, resp, options);
});
};
wrapError(this, options);
return this.sync('read', this, options);
}
});
这只是您尝试解决此问题的一个示例。我没有测试它,它可能不起作用,但我没有看到任何立即明显的原因为什么它不应该。
您可以覆盖 Issue
模型中的 sync method 以链接您的请求。
var Issue = Backbone.Model.extend({
urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues',
sync: function(method, model, options) {
if (method !== 'read')
return Backbone.sync.apply(this, arguments);
// first request
var xhr = Backbone.ajax({
type: 'GET',
dataType: 'json',
url: _.result(model, 'url')
});
// second request
return xhr.then(function (resp1) {
var markdown = new Markdown({text : resp1.body || 'body'});
var data = markdown.toJSON();
// the callback to fill your model, will call parse
var success = options.success;
return Backbone.ajax({
url: _.result(markdown, 'url'),
dataType: 'html',
contentType: 'application/json',
type: 'POST',
data: data
}).then(function(resp2) {
// sets the data you need from the response
var resp = _.extend({}, resp1, {
body: resp2
});
// fills the model and triggers the sync event
success(resp);
// transformed value returned by the promise
return resp;
});
});
}
});
传递给 Model.sync
的选项散列包含对 model.parse
的回调,当您对数据感到满意时,您可以使用它来设置模型的属性。
我有一个场景,模型的 fetch()
调用将 return 数据,属性 需要从中传递给另一个 API 和 return 中的类型 API 将是实际需要的数据。
var Issue = Backbone.Model.extend({
urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues',
parse: function(response, options){
var markdown = new Markdown({ text : response.body });
markdown.fetch({
contentType: 'application/json',
type: 'POST',
data: JSON.stringify( markdown.toJSON() ),
success: function(data){
response.body = data;
}
});
return response;
}
});
var Markdown = Backbone.Model.extend({
defaults:{
'text': '',
'mode' : 'markdown'
},
url: 'https://api.github.com/markdown'
});
因此,当 Issue
将被提取时:
var issue = new Issue({id: 1});
issue.fetch().then(function(){
//do stuff
});
它将有一个 body
的 属性 包含 markdown 语法文本,我需要将其传递给另一个 API 并获得将传递给查看的响应.
从上面可以看出,我尝试重写 parse
但它的 return 类型必须是一个对象, fetch
将是 async
那么我该怎么办在这里做这项工作?
注意:我知道在服务器中聚合数据然后接收它是最好的主意,但这在 atm 是不可能的。
我认为您必须覆盖模型的 fetch
才能使其正常工作
考虑一下默认提取的样子:
fetch: function(options) {
options = _.extend({parse: true}, options);
var model = this;
var success = options.success;
options.success = function(resp) {
var serverAttrs = options.parse ? model.parse(resp, options) : resp;
if (!model.set(serverAttrs, options)) return false;
if (success) success.call(options.context, model, resp, options);
model.trigger('sync', model, resp, options);
};
wrapError(this, options);
return this.sync('read', this, options);
},
(github)
该实现不支持 model.parse
的异步版本,但由于您使用 .extend
创建模型 class,您可以用自己的实现覆盖它,所以让我们看看确实如此。它需要一个 options
对象,创建一个 success
回调,然后委托给 Backbone.Sync
.
正是那个调用 parse
的回调,这就是支持异步所需要的。
最快、最肮脏的方法可能就是复制和修改现有的默认提取。
var MyModel = Backbone.Model.extend({
fetch: function(options) {
options = _.extend({parse: true}, options);
var model = this;
var success = options.success;
options.success = function(resp) {
function parser(resp, options, cb) {
...do your async request stuff and call cb with the result when done...
}
parser(resp, options, function(result) {
if (!model.set(result, options)) return false;
if (success) success.call(options.context, model, resp, options);
model.trigger('sync', model, resp, options);
});
};
wrapError(this, options);
return this.sync('read', this, options);
}
});
这只是您尝试解决此问题的一个示例。我没有测试它,它可能不起作用,但我没有看到任何立即明显的原因为什么它不应该。
您可以覆盖 Issue
模型中的 sync method 以链接您的请求。
var Issue = Backbone.Model.extend({
urlRoot: 'https://api.github.com/repos/ibrahim-islam/ibrahim-islam.github.io/issues',
sync: function(method, model, options) {
if (method !== 'read')
return Backbone.sync.apply(this, arguments);
// first request
var xhr = Backbone.ajax({
type: 'GET',
dataType: 'json',
url: _.result(model, 'url')
});
// second request
return xhr.then(function (resp1) {
var markdown = new Markdown({text : resp1.body || 'body'});
var data = markdown.toJSON();
// the callback to fill your model, will call parse
var success = options.success;
return Backbone.ajax({
url: _.result(markdown, 'url'),
dataType: 'html',
contentType: 'application/json',
type: 'POST',
data: data
}).then(function(resp2) {
// sets the data you need from the response
var resp = _.extend({}, resp1, {
body: resp2
});
// fills the model and triggers the sync event
success(resp);
// transformed value returned by the promise
return resp;
});
});
}
});
传递给 Model.sync
的选项散列包含对 model.parse
的回调,当您对数据感到满意时,您可以使用它来设置模型的属性。