Implementing retry logic in node-fetch api call

Viewed 338

I hope you will forgive the beginners question, I'm trying to implement a simple retry policy for an api call using node-fetch

This is being added to an existing repo using TypeScript so I'm using this also, hence the data definitions.

async checkStatus(custId: string,  expectedStatus: string) {
        const response = await fetch(
            `${'env.API_URL'}/api/customer/applications/${custId}`,
            {
                method: 'GET',
                headers: headers,
            },
        )
        expect(response.status, "Response status should be 200").to.be.equal(200)
        const resp = await response.json()
        expect(resp.status).to.contain(expectedStatus)
        return resp.status;
}

I am calling it like so

await this.checkApplicationStatus(custId, 'NEW')
await this.checkApplicationStatus(custId, 'EXISTING')//and so forth

Is there a neat way of retrying based on an unexpected expectedStatus ?

Again, I appreciate there may be many examples out there but as a beginner, I am struggling to see a good/best-practice approach so looking for someone to provide an example. I don't need to use Chai assertions, this was just my first attempt.

TIA

1 Answers

you can check a library that I've published @teneff/with-retry

to use it you'll have to define error classes like these:

class UnexpectedStatus extends Error {
  constructor(readonly status: number) {
    super("Unexpected status returned from API");
  }
}

class ResourceNotFound extends Error {
  constructor() {
    super("Resource not found in API");
  }
}

and throw respectively depending on the status code:

export const getCustomerApplications = async ( custId, headers ) => {
  const result = await fetch(`https://example.com/api/customer/applications/${custId}`, {
    method: "GET",
    headers,
  });

  if (result.status === 404) {
    throw new ResourceNotFound();
  } else if (result.status > 200) {
    throw new UnexpectedStatus(result.status);
  }
  return result;
};

and then just use the HOF from the library to wrap your function, with options (how many retries should be attempted and for which errors should it be retrying)

const retryWhenReourceNotFoundOrUnexpectedStatus = withRetry({
  errors: [UnexpectedStatus, ResourceNotFound],
  maxCalls: 3,
});

const getCustomerApplicationsWithRetry =
  retryWhenReourceNotFoundOrUnexpectedStatus(getCustomerApplications);

const result = await getCustomerApplicationsWithRetry(1234, {
  Authorization: "Bearer mockToken",
});

Check this working setup

Related