github.com/manicqin/nomad@v0.9.5/ui/app/adapters/watchable.js (about) 1 import { get } from '@ember/object'; 2 import { assign } from '@ember/polyfills'; 3 import { inject as service } from '@ember/service'; 4 import queryString from 'query-string'; 5 import ApplicationAdapter from './application'; 6 import { AbortError } from '@ember-data/adapter/error'; 7 8 export default ApplicationAdapter.extend({ 9 watchList: service(), 10 store: service(), 11 12 ajaxOptions(url, type, options) { 13 const ajaxOptions = this._super(...arguments); 14 const abortToken = (options || {}).abortToken; 15 if (abortToken) { 16 delete options.abortToken; 17 18 const previousBeforeSend = ajaxOptions.beforeSend; 19 ajaxOptions.beforeSend = function(jqXHR) { 20 abortToken.capture(jqXHR); 21 if (previousBeforeSend) { 22 previousBeforeSend(...arguments); 23 } 24 }; 25 } 26 27 return ajaxOptions; 28 }, 29 30 findAll(store, type, sinceToken, snapshotRecordArray, additionalParams = {}) { 31 const params = assign(this.buildQuery(), additionalParams); 32 const url = this.urlForFindAll(type.modelName); 33 34 if (get(snapshotRecordArray || {}, 'adapterOptions.watch')) { 35 params.index = this.watchList.getIndexFor(url); 36 } 37 38 const abortToken = get(snapshotRecordArray || {}, 'adapterOptions.abortToken'); 39 return this.ajax(url, 'GET', { 40 abortToken, 41 data: params, 42 }); 43 }, 44 45 findRecord(store, type, id, snapshot, additionalParams = {}) { 46 let [url, params] = this.buildURL(type.modelName, id, snapshot, 'findRecord').split('?'); 47 params = assign(queryString.parse(params) || {}, this.buildQuery(), additionalParams); 48 49 if (get(snapshot || {}, 'adapterOptions.watch')) { 50 params.index = this.watchList.getIndexFor(url); 51 } 52 53 const abortToken = get(snapshot || {}, 'adapterOptions.abortToken'); 54 return this.ajax(url, 'GET', { 55 abortToken, 56 data: params, 57 }).catch(error => { 58 if (error instanceof AbortError) { 59 return; 60 } 61 throw error; 62 }); 63 }, 64 65 reloadRelationship(model, relationshipName, options = { watch: false, abortToken: null }) { 66 const { watch, abortToken } = options; 67 const relationship = model.relationshipFor(relationshipName); 68 if (relationship.kind !== 'belongsTo' && relationship.kind !== 'hasMany') { 69 throw new Error( 70 `${relationship.key} must be a belongsTo or hasMany, instead it was ${relationship.kind}` 71 ); 72 } else { 73 const url = model[relationship.kind](relationship.key).link(); 74 let params = {}; 75 76 if (watch) { 77 params.index = this.watchList.getIndexFor(url); 78 } 79 80 // Avoid duplicating existing query params by passing them to ajax 81 // in the URL and in options.data 82 if (url.includes('?')) { 83 const paramsInUrl = queryString.parse(url.split('?')[1]); 84 Object.keys(paramsInUrl).forEach(key => { 85 delete params[key]; 86 }); 87 } 88 89 return this.ajax(url, 'GET', { 90 abortToken, 91 data: params, 92 }).then( 93 json => { 94 const store = this.store; 95 const normalizeMethod = 96 relationship.kind === 'belongsTo' 97 ? 'normalizeFindBelongsToResponse' 98 : 'normalizeFindHasManyResponse'; 99 const serializer = store.serializerFor(relationship.type); 100 const modelClass = store.modelFor(relationship.type); 101 const normalizedData = serializer[normalizeMethod](store, modelClass, json); 102 store.push(normalizedData); 103 }, 104 error => { 105 if (error instanceof AbortError) { 106 return relationship.kind === 'belongsTo' ? {} : []; 107 } 108 throw error; 109 } 110 ); 111 } 112 }, 113 114 handleResponse(status, headers, payload, requestData) { 115 // Some browsers lowercase all headers. Others keep them 116 // case sensitive. 117 const newIndex = headers['x-nomad-index'] || headers['X-Nomad-Index']; 118 if (newIndex) { 119 this.watchList.setIndexFor(requestData.url, newIndex); 120 } 121 122 return this._super(...arguments); 123 }, 124 });