This content originally appeared on DEV Community and was authored by John Wu
Currently most front-end request libraries use two hooks functions to handle requests and responses, which becomes difficult to maintain when we add too much business logic to the request.
The onion model is a very elegant technique for handling requests and responses, and we have a very mature application for it in node development, so why don't I let the front-end requests change to this way as well?
Here is a simple prototype example:
/**
* Composer
* https://github.com/reduxjs/redux/commit/44dfc39c3f8e5e8b51eeab7c44057da6c1086752
* @param {[fuction]} funcs middleware list
* @return {function} (...args) => f1(f2(f3(...args)))
*/
const compose = (funcs) => funcs.reduce((a, b) => (...args) => a(b(...args)));
// middlewares
const middleware1 = (next) => async (req) => {
console.log("1");
const res = await next(req);
console.log("1");
return res;
};
const middleware2 = (next) => async (req) => {
console.log("2");
const res = await next(req);
console.log("2");
return res;
};
const middleware3 = (next) => async (req) => {
console.log("3");
const res = await next(req);
console.log("3");
return res;
};
/**
* This can be replaced with: fetch, XMLRequest
*/
const adapter = ({ params }) => {
console.log("request");
// mock ruquest
return Promise.resolve(`Hello ${params.username}, I'm mock data.`);
};
/**
* Http method
*/
const get = async (path, params) => {
const dispatch = compose([middleware1, middleware2, middleware3]);
return dispatch(adapter)({ path, params });
};
/**
* Mock login
*/
const login = async () => {
const res = await get("/api/login", { username: "John" });
console.log(res);
};
login();
// --- Login output: ----
/**
* 1
* 2
* 3
* request
* 3
* 2
* 1
* Hello John, I'm mock data.
*/
Change one request processing to middleware, e.g. error interception, event tracking, refresh token, etc. Each function is a separate middleware, there is no coupling between them, we can easily remove or add a middleware and the code will work fine
We no longer have to split the logic at a request into two separate hooks' methods
I think this is a perfect way to intercept requests, and I've turned this idea into a project
It looks like this:
import Resreq from 'resreq'
const resreq = new Resreq({
baseUrl: 'https://example.com'
})
// Intercepting responses and requests using middleware
resreq.use((next) => async (req) => {
try {
console.log(req) // Request can be changed here
const res = await next(req)
console.log(res) // Response can be changed here
return res
} catch (error) {
console.log(error) // Catch errors here
throw error
}
})
const res = await resreq.get('/api', {
params: { foo: 'bar' }
})
console.log(res.json())
Github: https://github.com/molvqingtai/resreq
This content originally appeared on DEV Community and was authored by John Wu
John Wu | Sciencx (2022-03-24T16:23:35+00:00) Applying Koa’s onion model to front-end requests. Retrieved from https://www.scien.cx/2022/03/24/applying-koas-onion-model-to-front-end-requests/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.