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

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

最近由于某种未知原因,我开始在控制台中看到常规错误。像这样:

(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)

它有时还会使我的机器人的延迟达到 30000 毫秒。

我的有趣命令中只有 Axios 部分,这是其中之一(但它仍然可以正常工作,只是记录错误):

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!');
        }

这以前不是什么东西。

由于您的 axios 调用没有捕获,因此出现此错误或警告是正常的。

管理 axios 请求以防止此类问题很重要。另外,我假设您显示的示例缺少一些数据,因为您不需要在捕获状态之外定义结果变量,所以我假设您有一个循环或其他可能导致这种情况的原因。

如果您在循环中或使用 Promise.all 调用同一端点,有时您需要限制并发请求。如果不是这样请忽略这部分。

首先,确保正确设置您的 axios.default.timeout 值以定义在有响应时取消请求的时间。

根据您的要求定义响应状态。

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

定义解析代码以确保您始终具有相同的结构。

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

定义一个 catch 功能来检查错误并决定是抛出错误还是只记录错误。

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

让我们在 .catch 的一次调用中使用它们。

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

如果我没记错的话,您不能直接从 promise 访问属性,因为从 属性 声明变量是同步的,而您的 url() 方法是异步的。
当未返回响应时,axios.get(url) 的数据类型为 Promise,因此它没有您早期访问的 data 属性。因此,您必须等待响应。当返回响应时,该方法的数据类型会更改为预期的类型。那时您可以访问 data 属性 所以我认为你的代码应该像下面这样:

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!');
}

假设这个代码块在异步上下文中,它应该可以正常工作。
我希望这个答案对你有用。