Retryable
Starting from Midway v3.5.0, method custom retry logic is supported.
Many times, we need to use try
multiple times to wrap the function and handle errors on some method calls that are prone to failure or asynchronous.
For example:
// Defines an asynchronous function
async function invoke(id) {
// Some remote call logic
}
async invokeNew() {
let error;
try {
return await invoke(1);
} catch(err) {
error = err;
}
try {
return await invoke(2);
} catch(err) {
error = err;
}
if (error) {
// ....
}
}
You may try to call the invoke
operation multiple times and use the try/catch to catch exceptions, resulting in repeated and lengthy business code writing.
Define retry functions
We can use retryWithAsync
method to package and simplify the whole process.
import { retryWithAsync } from '@midwayjs/core';
async function invoke(id) {
// ...
}
async function someServiceMethod() {
// The default call, plus two retries, can be executed up to three times.
const invokeNew = retryWithAsync(invoke, 2);
try {
return await invokeNew(1);
} catch(err) {
// err
}
}
The method parameters and return values after the package are exactly the same as the original method.
When the call is successful within the retry period and no error is thrown, the successful return value will be returned.
If it fails, the MidwayRetryExceededMaxTimesError
exception will be thrown.
If it is used in a class, you may need to pay attention to the point of this
.
Examples are as follows:
import { retryWithAsync } from '@midwayjs/core';
export class UserService {
async getUserData(userId: string) {
// wrap
const getUserDataOrigin = retryWithAsync(
this.getUserDataFromRemote,
2,
{
receiver: this
}
);
// invoke
return getUserDataOrigin(userId);
}
async getUserDataFromRemote(userId: string) {
// get data from remote
}
}
This binding
Starting from Midway v3.5.1, a receiver
parameter has been added to bind this in the scene of the class for processing:
- 1, the method of correct this point
- 2, the correctness of the definition of the package method.
// wrap
const getUserDataOrigin = retryWithAsync(
this.getUserDataFromRemote,
2,
{
receiver: this, // This parameter is used to handle this pointing
}
);
If there is no such parameter, the code needs to be written as follows to bind this, and the definition of the getUserDataOrigin
method returned is correct.
// wrap
const getUserDataOrigin = retryWithAsync(
this.getUserDataFromRemote.bind(this) as typeof this.getUserDataFromRemote,
2,
{
receiver: this
}
);