This article was originally published at: github.com/bigo-fronte… Welcome to follow and reprint.

background

Bigo front-end began to promote BFF. Hello Farm, as the first BFF landing project, completed the landing practice from 0-1 in two months.

【 Node Combat Series 】 According to the small module split, from the developer’s point of view, how to carry out BFF high availability coding.

This series of articles is based on the EggJS framework and uses TS syntax. To improve your reading experience, it is recommended that you learn about EggJS first.

series

  • Write a retry decorator
  • 【 Node Combat Series 】 Self-realization of application cache
  • 【 Node Combat series 】 Asynchronous concurrency, custom Promise. AllSettled
  • 【 Node Actual Series 】 RPC and HTTP protocol communication
  • Use reqId to trace request process logs
  • 【 Node Combat series 】 Validate the input parameter
  • 【 Node Combat Series 】 Abnormal interruption
  • 【 Node Combat Series 】 Base64 encoding
  • 【 Node Combat Series 】 Service discovery
  • 【 Node Combat Series 】 Coding and convention
  • 【 Node Combat Series 】 Monitor alarms
  • 【 Node Combat Series 】 Unit test
  • 【 Node Combat Series 】 pressure test
  • 【 Node Combat Series 】 grayscale
  • 【 Node Combat Series 】 document
  • 【 Node Combat series 】 series summary

Please follow our Github blog for continuous updates. Github.com/bigo-fronte…

Why retry

This is very simple. In the project development, invoking the third-party interface will cause errors in the service called due to network delay or exceptions, and the invocation may succeed after several retries (for example, uploading pictures). Therefore, a retry mechanism is needed to retry the interface to ensure the normal execution of the interface.

Why decorators

Instead, we can wrap a retry method around the interface call, encoded as follows.

/** ** @param {number} retries * @param {Function} fn - retry Function */ const retry = (retries, fn) => { fn().catch((err) => retries > 1 ? retry(retries - 1, fn) : Promise.reject(err)); };Copy the code

But this nesting of functions is not elegant to read, and since we use TS to code, we should make the most of it and use it as a decorator.

A decorator is simply an extension of a class or its properties to add additional functionality.

What is a decorator

Let’s take a look at what the Retry decorator looks like in code

@retry(3, (res) => res.code ! == 0) public async initFarm() { const res = await this.request({ opType: Eoperator.BASE_INIT_FARM, }); return res; }Copy the code

Retry (3, (res) => res.code! == 0) is a decorator

@ as identifier, can be applied to class, can also be applied to the attributes of the class, specific please check the document principle using www.tslang.cn/docs/handbo…

Method decorator

Our retry decorator is a method decorator, and we’ll walk through the properties of the method decorator first

Here is an example of a method decorator (@Enumerable) that applies to a method of the Greeter class:

class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } @enumerable(false) greet() { return "Hello, " + this.greeting; }}Copy the code

We can define the @Enumerable decorator with the following function declaration:

function enumerable(value: boolean) { console.log(value); // target is the class constructor for static members, For instance members that are prototype objects of the class // propertyKey member name // Descriptor property descriptor of the member return function (Target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.enumerable = value; }; }Copy the code

Implement retry decorator

/ / dormancy, Function sleep(duration) {return new Promise((reslove) => setTimeout(reslove, Duration))} /** * Retry decorator ** @param {number} retries number of tries * @param {*} cb Retry condition * @returns */ export function retry(retries: number, cb) { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { // 1. Save the method body const oldMethod = Description. value; Value = async function(... Const loop = async (count) => {// 3. Const res = await oldmethod. apply(this, args); if (count > 1 && cb(res)) { sleep(100); Return loop(--count); } else { return res; }}; return loop(retries); }}}Copy the code

summary

Reviewing the whole article, we found that a small and beautiful retry decorator is implemented, and I hope you can also start to encapsulate your own decorators.

Welcome everyone to leave a message to discuss, wish smooth work, happy life!

I’m bigO front. See you next time.