Reputation: 69
I have to return an await function from my code block, now when the await function is called and failed on the first try, I want to retry it again and if it failed on the second time.. I will show an error message.
THIS IS MY CODE
async makeCall(inputs: myInputs): Promise<Instance> {
const emailOptions: CreateOptions = {
to: inputs.toPhone,
from: this.config.accountPhoneNumber
};
if (inputs.toPhone) {
emailOptions.sendText = inputs.toPhone;
}
return await this.sample.create(emailOptions);
}
I WANT SOMETHING LIKE THIS OR ANY SUGGESTION? LIKE Retry from RxJs
for(var i = 0; i < 1; i++)
{
var result = await this.sample.create(emailOptions);
if(result)
{
// break the loop
return result;
}
}
// if we land here, so the number of retries was exceeded
throw Error("...");
Upvotes: 4
Views: 98
Reputation: 25940
Sometimes, a generic approach, without RxJs is simpler and better ;)
Here's generic (flexible and reusable) approach to retrying an async operation:
// retry-status object:
// - "index": retry index, starting from 0
// - "duration": retry overall duration, in ms
// - "error": last error, if available
type RetryStatus = { index: number, duration: number, error?: any };
// retry-status callback;
type RetryCB<T> = (s: RetryStatus) => T;
type RetryOptions = {
// maximum number of retries (infinite by default),
// or a callback to indicate the need for another retry;
retry?: number | RetryCB<Boolean>,
// retry delays, in ms, or a callback that returns them;
delay?: number | RetryCB<number>,
// error notifications;
error?: RetryCB<void>
};
// retries async operation returned from "func" callback, according to options;
// note that "func()" will receive "error" = undefined when "index" = 0.
function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
const start = Date.now();
let index = 0, e: any;
let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
const s = () => ({index, duration: Date.now() - start, error: e});
const c: () => Promise<T> = () => func(s()).catch(err => {
e = err;
typeof error === 'function' && error(s());
const r = typeof retry === 'function' ? retry(s()) : retry--;
const d = typeof delay === 'function' ? delay(s()) : delay;
index++;
const t = () => r ? c() : Promise.reject(e);
return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(t) : t();
});
return c();
}
You can still use it with RxJs, of course, because it is 100% generic. You just pass it a function that creates your async request, plus some optional parameters.
The code above was taken from this gist.
Upvotes: 1
Reputation: 352
if you call an api, best practice is to use an interceptor that retry your request in the following you can see:
@Injectable()
export class RetryInterceptorService implements HttpInterceptor {
private maxRetryAttempts = 3; // Number of retry attempts
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
retryWhen(errors =>
errors.pipe(
mergeMap((error, index) => {
if (index < this.maxRetryAttempts && this.shouldRetry(error)) {
return of(error).pipe(delay(1000)); // Retry after 1 second
}
return throwError(error);
})
)
),
catchError(this.handleError)
);
}
private shouldRetry(error: HttpErrorResponse): boolean {
// Define conditions under which to retry
return error.status >= 500; // Retry for server errors
}
private handleError(error: HttpErrorResponse) {
// Handle the error here
console.error('An error occurred:', error);
return throwError(() => new Error(error.message || 'Server Error'));
}
}
if you want to use retry for another place with rxjs just use pipe and retryWhen
Upvotes: 0
Reputation: 58199
You can use this article code which seems to be exactly what you need. It has support for number of retries and custom error message.
import './style.css';
let i = 0;
const promiseFn = () => {
const condition = i === 0;
i++;
return condition ? Promise.reject() : Promise.resolve();
};
const retryWithDelay = async (
fn: any,
retries = 3,
finalErr = 'Retry failed'
) => {
try {
// try
await fn();
} catch (err) {
// if no retries left
// throw error
if (retries <= 0) {
console.log('error');
return Promise.reject(finalErr);
}
//recursively call the same func
return retryWithDelay(fn, retries - 1, finalErr);
}
};
retryWithDelay(promiseFn, 2)
.then(() => {
console.log('final success');
})
.catch(() => {
console.log('final error');
});
Upvotes: 3