Browse Source

Refactor RemoteStorage

pull/4223/head
Artur Arseniev 4 years ago
parent
commit
076a1915fd
  1. 9
      src/storage_manager/config/config.js
  2. 167
      src/storage_manager/model/RemoteStorage.js

9
src/storage_manager/config/config.js

@ -25,9 +25,6 @@ export default {
checkLocal: true,
},
remote: {
// Custom parameters to pass with the remote request, eg. csrf token
params: {},
// Custom headers
headers: {},
@ -37,12 +34,6 @@ export default {
// Endpoint URL where to load data project
urlLoad: '',
//Callback before request
beforeSend(jqXHR, settings) {},
//Callback after request
onComplete(jqXHR, status) {},
// set contentType paramater of $.ajax
// true: application/json; charset=utf-8'
// false: 'x-www-form-urlencoded'

167
src/storage_manager/model/RemoteStorage.js

@ -1,146 +1,67 @@
import Backbone from 'backbone';
import fetch from 'utils/fetch';
import { isUndefined, isFunction } from 'underscore';
import { Model } from 'common';
import { isUndefined, isFunction, isString } from 'underscore';
export default Backbone.Model.extend({
fetch,
defaults: {
urlStore: '',
urlLoad: '',
params: {},
beforeSend() {},
onComplete() {},
contentTypeJson: false,
credentials: 'include',
fetchOptions: ''
},
/**
* Triggered before the request is started
* @private
*/
onStart() {
const em = this.get('em');
const before = this.get('beforeSend');
before && before();
},
/**
* Triggered on request error
* @param {Object} err Error
* @param {Function} [clbErr] Error callback
* @private
*/
onError(err, clbErr) {
if (clbErr) {
clbErr(err);
} else {
const em = this.get('em');
console.error(err);
em && em.trigger('storage:error', err);
}
},
/**
* Triggered on request response
* @param {string} text Response text
* @private
*/
onResponse(text, clb) {
const em = this.get('em');
const complete = this.get('onComplete');
const typeJson = this.get('contentTypeJson');
const parsable = text && typeof text === 'string';
const res = typeJson && parsable ? JSON.parse(text) : text;
complete && complete(res);
clb && clb(res);
em && em.trigger('storage:response', res);
},
store(data, clb, clbErr) {
const body = {};
for (let key in data) {
body[key] = data[key];
}
export default class RemoteStorage extends Model {
async store(data, opts = {}) {
await this.request(opts.urlStore, this.__props(opts, data), opts);
}
this.request(this.get('urlStore'), { body }, clb, clbErr);
},
async load(opts) {
return await this.request(opts.urlLoad, this.__props(opts), opts);
}
load(keys, clb, clbErr) {
this.request(this.get('urlLoad'), { method: 'get' }, clb, clbErr);
},
request(url, props = {}, opts = {}) {
return fetch(url, props)
.then(res => {
const result = res.text();
const isOk = ((res.status / 200) | 0) === 1;
return isOk ? result : result.then(Promise.reject);
})
.then(text => {
const parsable = text && isString(text);
return opts.contentTypeJson && parsable ? JSON.parse(text) : text;
});
}
/**
* Execute remote request
* @param {string} url Url
* @param {Object} [opts={}] Options
* @param {Function} [clb=null] Callback
* @param {Function} [clbErr=null] Error callback
* @private
*/
request(url, opts = {}, clb = null, clbErr = null) {
const typeJson = this.get('contentTypeJson');
const headers = this.get('headers') || {};
const params = this.get('params');
__props(opts = {}, data) {
const typeJson = opts.contentTypeJson;
const headers = opts.headers || {};
const fetchOpts = opts.fetchOptions || {};
const reqHead = 'X-Requested-With';
const typeHead = 'Content-Type';
const bodyObj = opts.body || {};
let fetchOptions;
let body;
for (let param in params) {
bodyObj[param] = params[param];
}
if (isUndefined(headers[reqHead])) {
headers[reqHead] = 'XMLHttpRequest';
}
// With `fetch`, have to send FormData without any 'Content-Type'
// https://stackoverflow.com/questions/39280438/fetch-missing-boundary-in-multipart-form-data-post
if (isUndefined(headers[typeHead]) && typeJson) {
headers[typeHead] = 'application/json; charset=utf-8';
}
if (typeJson) {
body = JSON.stringify(bodyObj);
} else {
body = new FormData();
if (data) {
if (typeJson) {
body = JSON.stringify(data);
} else {
body = new FormData();
for (let bodyKey in bodyObj) {
body.append(bodyKey, bodyObj[bodyKey]);
for (let key in data) {
body.append(key, data[key]);
}
}
}
fetchOptions = {
method: opts.method || 'post',
credentials: this.get('credentials'),
headers
};
// Body should only be included on POST method
if (fetchOptions.method === 'post') {
fetchOptions.body = body;
}
const fetchOpts = this.get('fetchOptions') || {};
const addOpts = isFunction(fetchOpts)
? fetchOpts(fetchOptions)
: fetchOptions;
const result = {
method: body ? 'post' : 'get',
credentials: opts.credentials,
headers,
body,
};
this.onStart();
this.fetch(url, {
...fetchOptions,
...(addOpts || {})
})
.then(res =>
((res.status / 200) | 0) == 1
? res.text()
: res.text().then(text => Promise.reject(text))
)
.then(text => this.onResponse(text, clb))
.catch(err => this.onError(err, clbErr));
return {
...result,
...(isFunction(fetchOpts) ? fetchOpts(result) : fetchOpts),
};
}
});
}

Loading…
Cancel
Save