ajax 如何为 ember.js 创建自定义适配器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17938294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you create a custom adapter for ember.js?
提问by carboncomputed
I'm planning on using ember.js, however my REST api doesn't exactly align with the packaged REST Adapter. I would like to "override" find and be able to put my own ajax in it. I dislike how an ember findAll retrieves all my documents with no options for pagination, so that along with other query parameters would be useful --which is why I want to write my own ajax. I've been unable to find any documentation on how I would go about doing this.
我打算使用 ember.js,但是我的 REST api 与打包的 REST 适配器并不完全一致。我想“覆盖” find 并能够将我自己的 ajax 放入其中。我不喜欢 ember findAll 如何在没有分页选项的情况下检索我的所有文档,以便与其他查询参数一起使用 - 这就是我想编写自己的 ajax 的原因。我一直无法找到任何关于我将如何执行此操作的文档。
回答by Kingpin2k
For Ember Data
对于 Ember 数据
This is up to date as of Ember Data 1.0 beta 9.
这是 Ember Data 1.0 beta 9 的最新版本。
Extend one of the Ember Data Adapters. To make it site wide:
扩展 Ember 数据适配器之一。要使其站点范围广:
App.ApplicationAdapter = DS.RESTAdapter.extend(....
To make it model specific:
要使其特定于模型:
App.FooAdapter = DS.RESTAdapter.extend(...
Then you will define the implementation you'd like to override. You always have the option to call this._superand revert to the base implementation. e.g.
然后,您将定义要覆盖的实现。您始终可以选择调用this._super并恢复到基本实现。例如
App.NotesAdapter = DS.RESTAdapter.extend({
find: function(store, type, id) {
id = "foo" + id;
return this._super(store, type, id);
}
});
Or you can completely override the implementation:
或者您可以完全覆盖实现:
App.NotesAdapter = DS.RESTAdapter.extend({
find: function(store, type, id) {
// Do your thing here
return this.ajax(this.buildURL(type.typeKey, id), 'GET');
},
findAll: function(store, type, sinceToken) {
// Do your thing here
var query;
if (sinceToken) {
query = { since: sinceToken };
}
return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
},
findQuery: function(store, type, query) {
// Do your thing here
return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
},
findMany: function(store, type, ids, owner) {
return this.ajax(this.buildURL(type.typeKey), 'GET', { data: { ids: ids } });
},
.....
});
To see the complete api you can override see: http://emberjs.com/api/data/classes/DS.RESTAdapter.html
要查看完整的 api,您可以覆盖:http: //emberjs.com/api/data/classes/DS.RESTAdapter.html
Serializer
序列化器
Often more important will be rolling your own serializer for massaging the data to fit your rest endpoint. Here's some useful information from the transition document https://github.com/emberjs/data/blob/master/TRANSITION.md.
通常更重要的是滚动你自己的序列化器来按摩数据以适应你的休息端点。以下是转换文档https://github.com/emberjs/data/blob/master/TRANSITION.md 中的一些有用信息。
The short version is that once an Ajax request has completed, the resulting payload is sent through the following hooks:
简短的版本是,一旦 Ajax 请求完成,生成的有效负载将通过以下钩子发送:
- The payload is sent to extractSingle if the original request was for a single record (like find/save) or extractArray if the original request was for an Array of records (like findAll/findQuery)
- The default behavior of those methods is to pull apart the top-level of the payload into multiple smaller records.
- Each of those smaller records is sent to normalize, which can do normalization a record at a time.
- Finally, specific types of records can be specially normalized.
- 如果原始请求是针对单个记录(例如 find/save)或 extractArray,如果原始请求是针对记录数组(例如 findAll/findQuery),则将有效负载发送到 extractSingle
- 这些方法的默认行为是将有效负载的顶层拆分为多个较小的记录。
- 这些较小的记录中的每一个都被发送到归一化,它可以一次对一个记录进行归一化。
- 最后,可以对特定类型的记录进行特殊规范化。
App.PostSerializer = DS.RESTSerializer.extend({
extractSingle: function(store, type, payload, id) {
// massage
this._super(store, type, payload, id);
},
extractArray: function(store, type, payload) {
// massage
this._super(store, type, payload);
},
normalize: function(type, hash, property) {
// massage
this._super(type, hash, property);
}
});
- use extractSingle and extractArray when the top-level of your payload is organized differently than Ember Data expects
- use normalize to normalize sub-hashes if all sub-hashes in the payload can be normalized in the same way.
- use normalizeHash to normalize specific sub-hashes.
- make sure to call super if you override extractSingle, extractArray or normalize so the rest of the chain will get called.
- 当有效负载的顶级组织与 Ember Data 预期的不同时,请使用 extractSingle 和 extractArray
- 如果有效载荷中的所有子哈希都可以以相同的方式标准化,则使用 normalize 来标准化子哈希。
- 使用 normalizeHash 来规范化特定的子哈希。
- 如果您覆盖了 extractSingle、extractArray 或 normalize,请确保调用 super 以便调用链的其余部分。
Rolling your own
滚动你自己的
App.FooAdapter = Ember.Object.extend({
find: function(id){
return $.getJSON('http://www.foolandia.com/foooo/' + id);
}
});
Then from your route, or wherever
然后从你的路线,或任何地方
App.FooRoute = Ember.Route.extend({
model: function(){
var adapter = App.FooAdapter.create();
return adapter.find(1);
}
});
Now personally I'd inject the adapter onto the routes just to make my life easier:
现在我个人将适配器注入路由只是为了让我的生活更轻松:
App.initializer({
name: "fooAdapter",
initialize: function (container, application) {
application.register("my:manager", application.FooAdapter);
application.inject("controller", "fooAdapter", "my:manager");
application.inject("route", "fooAdapter", "my:manager");
}
});
Then on the route you could be lazier and do:
然后在路线上,您可以更懒惰并执行以下操作:
App.FooRoute = Ember.Route.extend({
model: function(){
return this.fooAdapter.find(1);
}
});
Example: http://emberjs.jsbin.com/OxIDiVU/676/edit
示例:http: //emberjs.jsbin.com/OxIDiVU/676/edit
You can read more about Ember without Ember Data: Ember without Ember Data
你可以阅读更多关于 Ember without Ember Data: Ember without Ember Data
回答by traviss0
I had the same problem. I too wanted to use a slightly different format with my backend (cakePHP) and could not figure out how to do it. The previous answers are great but you might not need to redefine every method but simply change the format of the URL by overriding the buildURL in the RESTAdapter.
我有同样的问题。我也想在我的后端 (cakePHP) 中使用稍微不同的格式,但不知道该怎么做。前面的答案很好,但您可能不需要重新定义每个方法,而只需通过覆盖 RESTAdapter 中的 buildURL 来更改 URL 的格式。
For example, I want to use cakePHP's extension and want my urls to looks like so, application wide:
例如,我想使用 cakePHP 的扩展并希望我的 url 看起来像这样,应用程序范围:
- /users.json (findAll)
- /users/view/1.json (find)
- /users/delete/1.json
- /users/edit.json (POST)
- /users/add.json (POST)
- /users.json (findAll)
- /users/view/1.json(查找)
- /用户/删除/1.json
- /users/edit.json (POST)
- /users/add.json (POST)
After much hair pulling and the realization that ember-data is essential I used the following code:
经过大量的头发拉扯并意识到 ember-data 是必不可少的,我使用了以下代码:
App.ApplicationAdapter = DS.RESTAdapter.extend({
buildURL: function(type, id) {
var url = '/' + this.pluralize(type.typeKey);
if (id) {
url += '/' + id;
}
url += '.json';
return url;
}
});
Ember's docs are good, but most of their examples use FIXTURE data. I wish they had a simple example how to write different types of adapters for different situations.
Ember 的文档很好,但他们的大多数示例都使用 FIXTURE 数据。我希望他们有一个简单的例子,如何为不同的情况编写不同类型的适配器。
回答by Alexander Suleymanov
For those who code adapter themselves, if you need to return a value from your adapter (for example, userId), you can either return json or promise. Here is example of returning promise:
对于那些自己编码适配器的人,如果您需要从适配器返回一个值(例如,userId),您可以返回 json 或 promise。这是返回承诺的示例:
App.RequestAdapter = Ember.Object.extend({
newRequest: function (data) {
return new Ember.RSVP.Promise(function (resolve, reject) {
Ember.$.ajax({
type: 'POST', // method post
url: '/Request/Create', //target url
data: JSON.stringify(data), //the JSON.stringify converts data to JSON
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (response) {
resolve(response);
},
error: function (reason) {
reject(reason);
}
});
});
}
});
//use this adapter in your controller
var adapter = App.RequestAdapter.create();
adapter.newRequest(data).then(function (response) { //newRequest is method of our adapter
console.log(response.userId); //specify response data
}, function(error){
//handle error
});
You can get more info about Ember promises here: https://hackhands.com/3-ways-ember-js-leverages-promises/or here http://emberjs.com/api/classes/RSVP.Promise.html
您可以在此处获取有关 Ember 承诺的更多信息:https: //hackhands.com/3-ways-ember-js-leverages-promises/或在此处http://emberjs.com/api/classes/RSVP.Promise.html

