sediste
Version:
249 lines (185 loc) • 8.29 kB
JavaScript
export default class REST {
constructor(server_address){
/**
* Адрес серва
* @type {string}
*/
this.SERVER = server_address === undefined ? "http://localhost/" : server_address;
this.SERVER = this.SERVER.substr(this.SERVER.length-2, 1) === '/' ? this.SERVER.substr(0,this.SERVER.length-1) : this.SERVER;
/**
* Стандартное число запросов на страницу
* @type {number}
*/
this.perPageDefault = 20;
}
/**
*
* @param {string} url Адрес
* @param {object|string} params Параметры, которые надо передать, могут быть в виде объекта или строки
* @param {string} type Тип
*/
request(url, params, type = 'GET') {
// Нормализуем параметры, если они есть
if (typeof params === "object") {
params = JSON.stringify(params);
}
// Фетч поддерживается - получаем через него, это быстрее
if(typeof fetch === "function") {
return new Promise(async (resolve,reject)=>{
// Тело ответа формируется в два этапа: сперва заголовки, затем ответ
let ResolveBody = {};
// Делаем запрос
fetch(url,
{
method: type,
mode: 'cors',
body: params,
headers: {
'Content-type': 'application/json; charset=utf-8'
},
}
).then(response=>{
// Ответ получен
// Ответ с ошибкой
if (response.status !== 200) {
console.log('Ошибка загрузки [' + response.status + '] ' + url + ": " + response.statusText);
reject({
status: response.status,
message: response.statusText
});
return;
}
// Загрузка успешна
// Если в заголовках указана паджинация
let pages = undefined;
if (response.headers.get('X-Pagination-Current-Page') !== null) {
pages = {
page: parseInt(response.headers.get('X-Pagination-Current-Page')),
perPage: parseInt(response.headers.get('X-Pagination-Per-Page')),
count: parseInt(response.headers.get('X-Pagination-Page-Count')),
total: parseInt(response.headers.get('X-Pagination-Total-Count')),
}
}
// Заполняем тело ответа заголовками
ResolveBody = {
status: response.status,
type: "json",
data: {},
pages: pages
};
// Декодируем тело ответа
return response.json();
}).then(response=>{
// Декодируем тело ответа и возвращаем успешную загрузку
ResolveBody.data = response;
resolve(ResolveBody);
}).catch(err=>{
// Ошибка загрузки, не связанная с ХТТП, например обрыв соединения
// TODO: на этом этапе стоит сделать, чтобы он пробовал повторить запрос, если это GET
console.log('Ошибка загрузки [' + 0 + '] ' + url + ": Нет соединения с сервером");
reject({
status: 0,
message: "Нет соединения с сервером"
});
})
});
}
// Фетч не поддерживается - возвращаем промисифицированный XHR
else {
return new Promise((resolve, reject) => {
// Генерим новый запрос
let xhr = new XMLHttpRequest();
xhr.open(type, url, true);
// Автоматический парсинг json ответа
xhr.responseType = 'json';
// Запрос тоже в json
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
// Запрос между доменами свободный, если это dev-среда
xhr.withCredentials = false;
// Отправляем запрос
xhr.send(params === undefined ? null : params);
xhr.onload = function () {
// Ошибка загрузки
if (xhr.status !== 200) {
console.log('Ошибка загрузки [' + xhr.status + '] ' + url + ": " + xhr.statusText);
return reject({
status: xhr.status,
message: xhr.statusText
});
}
// Загрузка успешна
// Если в заголовках указана паджинация
let pages = undefined;
if (xhr.getResponseHeader('X-Pagination-Current-Page') !== null) {
pages = {
page: parseInt(xhr.getResponseHeader('X-Pagination-Current-Page')),
perPage: parseInt(xhr.getResponseHeader('X-Pagination-Per-Page')),
count: parseInt(xhr.getResponseHeader('X-Pagination-Page-Count')),
total: parseInt(xhr.getResponseHeader('X-Pagination-Total-Count')),
}
}
return resolve({
status: xhr.status,
type: xhr.responseType,
data: xhr.response,
pages: pages
});
};
// Ошибка загрузки, не связанная с ХТТП, например обрыв соединения
// TODO: на этом этапе стоит сделать, чтобы он пробовал повторить запрос, если это GET
xhr.onerror = function () {
console.log('Ошибка загрузки [' + 0 + '] ' + url + ": Нет соединения с сервером");
return reject({
status: 0,
message: "Нет соединения с сервером"
});
};
});
}
}
/**
* Получить выборку из таблицы через REST
* @param table
* @param fields
* @param where Позволяет делать выборку из связанных таблиц, надо только их указать через название таблицы sites.id=5, и указать колонку в expand
* @param expand
* @param sortfields
* @param page
* @param perPage
* @return Promise<>
*/
get(table, where, expand, fields, sortfields, page, perPage) {
// Генерим запрос
let query = this.SERVER + '/api/' + table;
let json = {};
// Генерим условия
if(where!==undefined && where!==null)
json.where = where;
if(fields !== undefined && fields!==null)
json.fields = fields;
if(sortfields !== undefined && sortfields!==null)
json.sort = sortfields;
if(expand !== undefined && expand!==null)
json.expand = expand;
// Страницы
json['per-page'] = perPage === undefined ? this.perPageDefault : perPage;
json['page'] = page === undefined ? 1 : page;
return this.request(query, JSON.stringify(json), 'POST');
}
/**
* Создать новую запись
* @param table
* @param values
*/
create(table, values) {
return this.request(this.SERVER + '/api/' + table + '/create', JSON.stringify(values), 'POST');
}
/**
* Удалить запись
* @param table
* @param id
*/
remove(table, id) {
return this.request(this.SERVER + '/api/' + table + '/delete?id=' + id , '{}', 'DELETE');
}
}