Автор Ли Тоу Ант Техническая группа по работе с финансовыми данными
задний план
В процессе разработки бизнес-приложений среднего уровня мы обнаружили следующие проблемы в ссылке запроса:
- Библиотеки запросов разные, а единообразия нет.Каждый раз, когда запускается новое приложение, набор логики уровня запросов необходимо повторно реализовывать, а API библиотеки запросов необходимо заново изучать при переключении приложений.
- Несоответствия дизайна интерфейса каждого приложения, путаница.Студентам, работающим с фронтендом и бэкендом, необходимо каждый раз переделывать формат интерфейса, а студентам фронтенда нужно заново понимать формат интерфейса при переключении приложений, прежде чем заняться развитием бизнеса.
- Документация интерфейса поддерживается различными способами.Некоторые из них находятся в Yuque (облачной базе знаний), некоторые в RAP (инструмент управления интерфейсом с открытым исходным кодом), а некоторые можно узнать, только прочитав исходный код Будь то техническое обслуживание, имитация данных или общение, это пустая трата рабочей силы. .
В ответ на вышеперечисленные вопросы предлагаемУправление уровнем запроса,надеяться наЧерез унифицированную библиотеку запросов, спецификацию дизайна интерфейса запроса спецификации, документ унифицированного интерфейсаЭти три шага, три этапа запрошенной ссылкиэффективность и спецификация,Это снижает коммуникационные и трудовые затраты, которые разработчики тратят на проектирование интерфейса, обслуживание документации и разработку логики уровня запросов. в,В качестве базовой технической поддержки унифицированная библиотека запросов нуждается в заблаговременном создании базы для обеспечения стабильной и полной функциональной поддержки верхнего уровня, на основе чего и появился umi-request.
umi-request
umi-requestЭто библиотека HTTP-запросов с открытым исходным кодом, основанная на инкапсуляции выборки. Она призвана предоставить разработчикам унифицированный метод вызова API, упростить метод использования и предоставить общие функции уровня запроса:
- Автоматическая сериализация параметров URL
- Режим отправки данных POST упрощен
- Обработка возврата ответа упрощена
- обработка тайм-аута запроса
- запросить поддержку кеша
- Обработка кодирования GBK
- Единая обработка ошибок
- Запрос на отмену поддержки
- HTTP-запрос среды узла
- Механизм перехватчика
- Механизм промежуточного программного обеспечения Onion
Сходства и различия с выборкой и аксиомами?
характеристика | umi-request | fetch | axios |
---|---|---|---|
выполнить | fetch | Встроенная поддержка браузера | XMLHttpRequest |
запрос упрощен | ✅ | ❌ | ✅ |
пост упрощенный | ✅ | ❌ | ❌ |
тайм-аут | ✅ | ❌ | ✅ |
тайник | ✅ | ❌ | ❌ |
проверка ошибок | ✅ | ❌ | ❌ |
обработка ошибок | ✅ | ❌ | ✅ |
перехватчик | ✅ | ❌ | ✅ |
приставка | ✅ | ❌ | ❌ |
суффикс | ✅ | ❌ | ❌ |
процесс гбк | ✅ | ❌ | ❌ |
промежуточное ПО | ✅ | ❌ | ❌ |
отменить запрос | ✅ | ❌ | ✅ |
Нижний уровень umi-request отказывается от XMLHttpRequest, который имеет грубый дизайн и не соответствует разделению ответственности, и выбирает выборку, которая является более семантической и основана на стандартной реализации Promise (подробнее).смотрите подробности); в то же время изоморфизм удобнее использоватьisomorphic-fetch(в настоящее время встроено) и на основе различных сценариев бизнес-приложений для извлечения общих возможностей запросов и поддержки быстрой настройки, такой как пост-упрощение, префикс и суффикс, проверка ошибок и т. д.
Легко начать
Установить
npm install --save umi-request
Выполнить GET-запрос
import request from "umi-request";
request
.get("/api/v1/xxx?id=1")
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
// 也可将 URL 的参数放到 options.params 里
request
.get("/api/v1/xxx", {
params: {
id: 1
}
})
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
воплощать в жизнь POST просить
import request from "umi-request";
request
.post("/api/v1/user", {
data: {
name: "Mike"
}
})
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
Создание универсальной конфигурации
Запросы обычно имеют некоторые общие настройки, мы не хотим добавлять их по одному в каждом запросе, такие как общие префиксы, суффиксы, информация заголовка, обработка исключений и т. д., тогда мы можем передатьextendЧтобы создать новый экземпляр umi-request, чтобы уменьшить количество повторяющегося кода:
import { extend } from "umi-request";
const request = extend({
prefix: "/api/v1",
suffix: ".json",
timeout: 1000,
headers: {
"Content-Type": "multipart/form-data"
},
params: {
token: "xxx" // 所有请求默认带上 token 参数
},
errorHandler: function(error) {
/* 异常处理 */
}
});
request
.get("/user")
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
Встроенные возможности общих запросов
Fetch сам по себе не предоставляет таких возможностей, как тайм-аут запроса, кэширование, отмена и т. д., но часто требуется в бизнес-разработке, поэтому umi-request инкапсулирует и строит общие возможности запросов, чтобы уменьшить повторную разработку:
{
// 'params' 是即将于请求一起发送的 URL 参数,参数会自动 encode 后添加到 URL 中
// 类型需为 Object 对象或者 URLSearchParams 对象
params: { id: 1 },
// 'paramsSerializer' 开发者可通过该函数对 params 做序列化(注意:此时传入的 params 为合并了 extends 中 params 参数的对象,如果传入的是 URLSearchParams 对象会转化为 Object 对象
paramsSerializer: function (params) {
return Qs.stringify(params, { arrayFormat: 'brackets' })
},
// 'data' 作为请求主体被发送的数据
// 适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
// 必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: { name: 'Mike' },
// 'headers' 请求头
headers: { 'Content-Type': 'multipart/form-data' },
// 'timeout' 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求超过了 'timeout' 时间,请求将被中断并抛出请求异常
timeout: 1000,
// 'prefix' 前缀,统一设置 url 前缀
// ( e.g. request('/user/save', { prefix: '/api/v1' }) => request('/api/v1/user/save') )
prefix: '',
// 'suffix' 后缀,统一设置 url 后缀
// ( e.g. request('/api/v1/user/save', { suffix: '.json'}) => request('/api/v1/user/save.json') )
suffix: '',
// 'credentials' 发送带凭据的请求
// 为了让浏览器发送包含凭据的请求(即使是跨域源),需要设置 credentials: 'include'
// 如果只想在请求URL与调用脚本位于同一起源处时发送凭据,请添加credentials: 'same-origin'
// 要改为确保浏览器不在请求中包含凭据,请使用credentials: 'omit'
credentials: 'same-origin', // default
// 'useCache' 是否使用缓存,当值为 true 时,GET 请求在 ttl 毫秒内将被缓存,缓存策略唯一 key 为 url + params 组合
useCache: false, // default
// 'ttl' 缓存时长(毫秒), 0 为不过期
ttl: 60000,
// 'maxCache' 最大缓存数, 0 为无限制
maxCache: 0,
// 'charset' 当服务端返回的数据编码类型为 gbk 时可使用该参数,umi-request 会按 gbk 编码做解析,避免得到乱码, 默认为 utf8
// 当 parseResponse 值为 false 时该参数无效
charset: 'gbk',
// 'responseType': 如何解析返回的数据,当 parseResponse 值为 false 时该参数无效
// 默认为 'json', 对返回结果进行 Response.text().then( d => JSON.parse(d) ) 解析
// 其他(text, blob, arrayBuffer, formData), 做 Response[responseType]() 解析
responseType: 'json', // default
// 'errorHandler' 统一的异常处理,供开发者对请求发生的异常做统一处理,详细使用请参考下方的错误处理文档
errorHandler: function(error) { /* 异常处理 */ },
}
Механизм промежуточного программного обеспечения для облегчения расширения
Приложение сложной сцены имеет индивидуальные требования к обработке до и после запроса, в дополнение к базовой встроенной возможности также необходимо улучшить собственное расширение на основе этого введения umi-запроса ** механизм промежуточного программного обеспечения, ** Выберите тип модели KOA Circle:
(луковая диаграмма промежуточного программного обеспечения)
Как видно из рисунка выше, каждый слой луковых колец является промежуточным ПО, и запрос будет выполняться дважды через промежуточное ПО. Разработчики могут легко реализовать расширенную обработку до и после запроса в соответствии с потребностями бизнеса:
import request from "umi-request";
request.use(function(ctx, next) {
console.log("a1");
return next().then(function() {
console.log("a2");
});
});
request.use(function(ctx, next) {
console.log("b1");
return next().then(function() {
console.log("b2");
});
});
// 执行顺序如下:
// a1 -> b1 -> b2 -> a2
// 使用 async/await 能让结构、顺序更清晰明了:
request.use(async (ctx, next) => {
console.log("a1");
await next();
console.log("a2");
});
request.use(async (ctx, next) => {
console.log("b1");
await next();
console.log("b2");
});
const data = await request("/api/v1/a");
// 执行顺序如下:
// a1 -> b1 -> b2 -> a2
Принцип реализации
Так как же реализован промежуточный механизм лукового кольца? Он в основном состоит из массива промежуточного программного обеспечения и комбинации промежуточного программного обеспечения.Первый отвечает за хранение смонтированного промежуточного программного обеспечения, а второй отвечает за объединение промежуточного программного обеспечения в соответствии со структурой лука и возврат реальной исполняемой функции:
промежуточное ПО для хранения
class Onion {
constructor() {
this.middlewares = [];
}
// 存储中间件
use(newMiddleware) {
this.middlewares.push(newMiddleware);
}
// 执行中间件
execute(params = null) {
const fn = compose(this.middlewares);
return fn(params);
}
}
ПО промежуточного слоя композиции
в приведенном выше кодеcomposeЭто реализация функции комбинированного промежуточного программного обеспечения, и упрощенная логика выглядит следующим образом (смотрите подробности):
export default function compose(middlewares) {
return function wrapMiddlewares(params) {
let index = -1;
function dispatch(i) {
index = i;
const fn = middlewares[i];
if (!fn) return Promise.resolve();
return Promise.resolve(fn(params, () => dispatch(i + 1)));
}
return dispatch(0);
};
}
Функция компоновки проходитdispatch(0)Первое промежуточное ПО выполняется первымfn(params, () => dispatch(i +1))
и предоставить() => dispatch(i +1)
В качестве входных данных каждое промежуточное ПО может возвращаться и продолжать обрабатывать свою собственную транзакцию после выполнения следующего промежуточного ПО, пока все промежуточное ПО не будет завершено и выполнено.Promise.resolve()
, формируя промежуточный механизм лукового кольца.
Богатые возможности запроса
Сталкиваясь с приложениями с несколькими терминалами и несколькими устройствами, umi-request не только поддерживает HTTP-запросы браузера, но также удовлетворяет требованиям среды узла, пользовательским запросам ядра и другим возможностям.
Поддержка среды узла для отправки HTTP-запросов
Запросить поддержку среды Node на основе ISOMORPHIC-FETCH:
const umi = require("umi-request");
const extendRequest = umi.extend({ timeout: 10000 });
extendRequest("/api/user")
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
Возможность поддерживать пользовательский запрос ядра
Мобильные приложения обычно имеют свои собственные протоколы запросов, такие как запросы RPC. Внешний интерфейс будет вызывать клиентский API запросов через SDK. umi-request позволяет разработчикам инкапсулировать свои собственные возможности запросов, например:
// service/some.js
import request from "umi-request";
// 自定义请求内核中间件
function SDKRequest(ctx, next) {
const { req } = ctx;
const { url, options } = req;
const { __umiRequestCoreType__ = "normal" } = options;
if (__umiRequestCoreType__.toLowerCase() !== "SDKRequest") {
return next();
}
return Promise.resolve()
.then(() => {
return SDK.request(url, options); // 假设已经引入了 SDK 并且能通过 SDK 发起对应请求
})
.then(result => {
ctx.res = result; // 将结果注入到 ctx 的 res 里
return next();
});
}
request.use(SDKRequest, { core: true }); // 引入内核中间件
export async function queryUser() {
return request("/api/sdk/request", {
__umiRequestCoreType__: "SDKRequest", // 声明使用 SDKRequest 来发起请求
data: []
});
}
Суммировать
С улучшением возможностей umi-request он смог поддерживать запросы из различных сценариев и конечных приложений.Для фронтенд-разработки требуется только освоить набор вызовов API для реализации многоконечной разработки, больше не нужно обращать внимание на реализацию базового протокола и больше сосредоточиться на разработке интерфейса. Основываясь на этом, umi-request может делать больше вещей внизу, таких как фиктивные данные, автоматическая идентификация типов запросов, мониторинг исключений интерфейса и отчетность, проверка спецификации интерфейса и т. д., и, наконец, достигать цели управления запросами. В umi-request еще много способностей, не упомянутых в тексте, если интересно, то ознакомьтесь.Подробная документация, если у вас есть хорошие предложения и потребности, вы также можете упомянутьissue.
giuthub blog Оригинальная ссылка