目前 Emberjs 框架中使用 JSONAPIAdapter 爲默認的 adapter,遵循 JSONAPI 的通訊標準。目前本公司也默認使用的是此 adapter,因此一下 api 均是在此基礎上。
另如無特殊說明,文內的文件結構均是在 Pods 目錄結構下的。
在 Ember Data 中,adapter 決定了如何向後端傳遞數據,提供了一些能夠設置的接口,如 格式化請求的URL ,設置請求的header 等。
在Emberjs 項目中,你能夠設置頂層的 application/adapter.js
也能夠在每一個對應的 model
(pods文件目錄)的文件中建立針對單個model
的adapter:modelName/adapter.js
。其中針對單個的 adapter.js
的優先權大於 application/adapter.js
。git
在 Ember Data 中默認使用的 DS.JSONAPIAdapter
中,若是要請求數據,能夠在route.js
中:github
// route.js model() { return this.get('store').findAll('post'); }
上面的請求默認發向的 url 爲/posts
,也就是 JSONAPIAdapter 會默認爲請求路徑轉換爲複數。ajax
提供了幾個默認的請求:json
Action | HTTP Verb | URL |
---|---|---|
Find 1 | GET | /posts/123 |
Find All 2 | GET | /posts |
Update 3 | PATCH | /posts/123 |
Create 4 | POST | /posts |
Delete 5 | DELETE | /posts/123 |
上文也提到了,在使用 JSONAPIAdapter 過程當中,會進行復數的轉換,包括對 modelName
也是,會進行轉換,好比說 咱們請求:後端
model(){ return this.get('store').findAll('campus'); }
在 JSONAPIAdapter
中會發送請求到 /campus
中,而尋找的 modelName
則是campu
這顯然不對,因此咱們須要對特殊字詞進行處理。
在 Ember Data 中使用的是 Ember Inflector 控制的複數轉換。一樣的,咱們也須要對它進行設置(pods目錄下):api
// app/app.js import './modules/custom-inflector-rules';
// app/modules/custom-inflector-rules.js import Inflector from 'ember-inflector'; const inflector = Inflector.inflector; // Tell the inflector that the plural of "campus" is "campuses" inflector.irregular('campus', 'campuses'); // Modules must have an export, so we just export an empty object here export default {};
而後能夠看到 請求發送的地址是/campuses
,尋找的 modelName
也是 campus
,如今變成正常的了,數據也是能夠正常顯示的了。數組
JSONAPIAdapter
提供瞭如下 porperties :緩存
這有篇文章講的這個屬性的使用。下面是具體的使用:
咱們先來看不設置此屬性的時候:服務器
// 後端返回的數據 'data': { 'type': 'post', 'id': 'idPost1', 'attributes': { 'title': 'post1', 'content': 'post content' }, 'relationships': { 'comments': { 'data': [ { 'id': 1, 'type': 'comment' }, { 'id': 2, 'type': 'comment' } ] } } }
這是post數據,當咱們請求 post
數據的時候:app
// route.js model() { return this.get('store').findRecord('post', 'idPost1'); }
這時候能夠看到 Ember Data 向 mirage 發送了兩條請求(須要設置 { async: true }
:
GET '/comments/1' GET '/comments/2'
在將coalesceFindRequests
屬性設置爲 true
的時候:
// comment/adapter.js import DS from 'ember-data'; export default DS.JSONAPIAdapter.extend({ coalesceFindRequests: true });
能夠看到如今只發送一條請求:
GET '/comments?filter[id]=1,2
defaultSerializer
這個屬性設置使用的 serializer
:
// post/adapter.js import DS from 'ember-data'; export default DS.JSONAPIAdapter.extend({ defaultSerializer: 'person' });
將使用 person/serializer.js
中的設定對 post
進行設定。
須要注意的是此屬性起做用的時候只有在此 model 的serializer.js
以及 application/serializer.js
不存在的時候起做用(Pods目錄)。
HTTP 消息頭容許客戶端和服務器經過 request和 response傳遞附加信息6。某一些 API 會須要一些請求頭,好比如今項目中使用到的 token,就是在每次進行請求的時候都攜帶這些請求頭數據發送給後端服務。通常不在init()
中設置header ,而是將其設爲計算屬性:
// post/adapter.js headers: computed(function () { return { 'dataType': 'json', 'contentType': 'application/json', 'Content-Type': 'application/json', 'Authorization': `bearer selfToken` }; })
請求頭就被改變了。
這樣就會在每次請求的時候攜帶本地的 token。
自定義主機,默認爲本地做用域。
顧名思義,定義命名空間的.
// adapter.js namespace: '/api/'
格式化請求的路徑:
// router this.get('store').findAll('bjCompany');
若是不在adapter.js
中進行設置,發送的請求是:
GET /bj-companies
也就是默認的轉換爲中劃線以及進行復數化,若是不想進行中劃線的轉換:
// bj-company/adapter.js import DS from 'ember-data'; import { camelize } from '@ember/string'; import { pluralize } from 'ember-inflector'; export default DS.JSONAPIAdapter.extend({ pathForType(type) { let newType = pluralize(camelize(type)); return newType; // newType: bjCompanies } });
這樣就達到了咱們的目的.
對URL 進行格式化,主要是進行復數化,能夠經過複寫 pathForType()
方法來達到重寫 URL 的目的.
JSONAPIAdapter
提供的關於 record 的一些 hook,可讓你複寫這些hook的邏輯來達到本身的目的,可是通常徹底符合 JSONAPI 的數據規範後,這些基本不用重寫.更多關於 Record 的部分請查詢 相關API以及其餘文檔.
這裏列舉出來 JSONAPIAdapter
中涉及 record 的一些 hook:
fetchRecord
用於生成在客戶端生成的 Record 的id.返回的值將分配給 record 的primaryKey
.通常不多使用.好比:
// bj-company/adapter.js generateIdForRecord(store, type, inputProperties) { return 343; }
新建立的 Record 的 id 就會變成 343(這裏只是演示做用).
返回 ajax 請求的數據或錯誤,若是想修改返回的數據規範或錯誤提示能夠在此處進行修改.
不多使用,視具體項目狀況而使用.
驗證若是是 422 錯誤,在handleResponse()
返回一個 InvalidError()
的實例.
請求返回成功,相應的status:
(status >= 200 && status < 300) || status === 304;
store使用此方法來肯定在store.findAll
使用緩存的記錄數組解析後,存儲是否應從新加載記錄數組。
默認爲 true
.
設爲false
以後,帶來的效果就是在本地兩個頁面同時顯示同一 model 實例,從一頁面跳轉到另外一頁面的時候不會再次請求數據.
// adapter.js shouldBackgroundReloadAll(store, snapshotArray) { return false; }
注意 這個方法只有在store 返回緩存數據以後才被調用.也就是當第一次請求數據的時候此方法不會被執行.
This method is only checked by the store when the store is returning a cached record array.
與上面同理.
當返回 true 的時候會馬上再次請求數據,若是返回false,會當即使用本地緩存.具體使用實例能夠查看 文檔
與上面同理.
對查詢的 參數 進行自定義排列,默認使用的是正序.
爲經過 store.createRecord()
建立的本地 record 在進行 record.save()
操做的時候構建 相應的 url
;
其餘的api 也相似:
JSONAPIAdapter 的相關API 的分析到此結束.
Written by FrankWang.