简体   繁体   中英

Discord.js: (node:147) UnhandledPromiseRejectionWarning: Error: timeout of 1000ms exceeded

So recently for some unknown reason, I started seeing regular errors in the console. Like this:

(node:147) UnhandledPromiseRejectionWarning: Error: timeout of 1000ms exceeded
    at createError (/home/runner/ricebot/node_modules/axios/lib/core/createError.js:16:15)
    at RedirectableRequest.handleRequestTimeout (/home/runner/ricebot/node_modules/axios/lib/adapters/http.js:280:16)
    at RedirectableRequest.emit (events.js:314:20)
    at RedirectableRequest.EventEmitter.emit (domain.js:483:12)
    at Timeout._onTimeout (/home/runner/ricebot/node_modules/follow-redirects/index.js:166:12)
    at listOnTimeout (internal/timers.js:554:17)
    at processTimers (internal/timers.js:497:7)

It also sometimes make my bot's latency go to 30000 ms.

I only have Axios parts in my fun commands and here is one of them (however it still works properly, just logs the error):

const url = 'https://no-api-key.com/api/v2/animals/cat';

        let image;
        let fact;
        try {
            const { data } = await axios.get(url);
            console.log(data);
            image = data.image;
            fact = data.fact;
        } catch (e) {
      console.log(e)
            return message.channel.send('An error occured, please try again!');
        }

This didn't use to be a thing.

Since your axios call doesn't have a catch it is normal to get this error or warning.

It is important to manage axios requests to prevent these kind of issues. Also, I assume, the sample you show is missing some data because you won't need to define result variables outside of the catch state, so I assume you have a loop or something that can cause this as well.

If you are making calls to same endpoint in a loop or with Promise.all, sometimes you need to limit concurrent requests. If it is not the case please ignore this part.

First of all, make sure to set your axios.default.timeout value correctly to define when to cancel the request if there was is response.

Define a response status check your with your requirements.

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  }
  const error: any = new Error(response.statusText);
  error.response = response;
  throw error;
}

Define a parse code to make sure you always have same structure.

function parseJSON(response) {
  return response.data;
}

Define a catch functionality to check errors and decide whether to throw errors or just log them.

function catchError(e){
  console.error(e);
  // TODO send a message
  return null;
}

Let's use them in a single call with.catch.

const myResult = await axios.get(url)
    .then(checkStatus)
    .then(parseJSON)
    .catch(catchError);
console.log(myResult);

if I'm not mistaken, you can't access properties from a promise directly, as declaring a variable from a property is synchronous while your url() method is asynchronous.
The data type of axios.get(url) is Promise when the response is not returned so it doesn't have a data property which you are accessing early on. Therefore you have to wait for the response. As when the response is returned the data type of that method changes to what it is intended to be. That's when you can access the data property So I think your code should be like the following:

const url = 'https://no-api-key.com/api/v2/animals/cat';
let image;
let fact;
try {
    const axiosUrl = await axios.get(url);
    const data = axiosUrl.data;
    console.log(data);
    image = data.image;
    fact = data.fact;
} catch (e) {
    console.log(e)
    return message.channel.send('An error occured, please try again!');
}

Assuming that this block of code is in an async context, it should work fine.
I hope this answer was of use for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM