2

Applying Koa's onion model to front-end requests

 2 years ago
source link: https://dev.to/molvqingtai/applying-koas-onion-model-to-front-end-requests-356p
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
John Wu

Posted on Mar 24

Applying Koa's onion model to front-end requests

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.
 */

Enter fullscreen mode

Exit fullscreen mode

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())

Enter fullscreen mode

Exit fullscreen mode

Github: https://github.com/molvqingtai/resreq


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK