首页 > 解决方案 > 尽管异步/等待,Discord bot 仍以错误的顺序发送消息

问题描述

我又遇到了这个异步编码问题,太烦人了。我想避免使用回调地狱并避免 startig withnew Promise和 resolve 所以我async/await改用它。

目标
我希望我的不和谐机器人按照定义的顺序在频道中一个接一个地吐出每个服务器状态。

问题
当然,输出的顺序是错误的。我知道每个服务器响应的速度是不同的。尽管使用async/await它仍然无法按我的意愿工作,这让我感到困惑。好像我用错了,就是不知道在哪里。我尝试使用循环迭代数组forEach并使用它,Promise.all()但它仍然不是正确的顺序。

我的代码 (MCVE)
我正在使用模块net来请求服务器状态,而对于这个 MCVE,我使用了 3 个随机主机。

const 
    status = require('net'),
    hosts = [
        ['Server #1', 'google.com', 80], 
        ['Server #2', 'jhfg87ed4.com', 80], // fake, just for response check
        ['Server #3', 'stackoverflow.com', 80]
    ]

const server = async (id, cb)=> {
    let host = hosts[id]
    const sock = new status.Socket()
    sock.setTimeout(2500)
    sock.on('connect', ()=> {
        cb(host[0]+': Up.')
        sock.destroy()
    }).on('error', e=> {
        cb(host[0]+': Down: '+e.message)
    }).on('timeout', e=> {
        cb(host[0]+' Down: timeout')
    }).connect(host[2], host[1])
}

async function results() { // wrong ?
    await server(0, cb => channel.send(cb))
    await server(1, cb => channel.send(cb))
    await server(2, cb => channel.send(cb))
}

输出:(随机顺序)

results() // not the order I wanted

Server #3: Up.
Server #1: Up.
Server #2: Down: getaddrinfo ENOTFOUND jhfg87ed4.com

解决方法(不好的做法)

server(0, cb => {
    channel.send(cb)
    server(1, cb => {
        channel.send(cb)
        server(2, cb => {
            channel.send(cb)
        })
    })
})

使用这个解决方法可以修复它并且像一个魅力一样工作,但我想避免这个回调地狱,因为它显然是不好的做法。

我会很感激任何帮助。

标签: javascriptnode.jspromiseasync-awaitdiscord.js

解决方案


脚本中的错误很少:

  • async不打电话await是没用的
  • 通常使用回调代替await,您不能同时使用
  • 通用回调接口是callback(error, data),所以你应该遵循这个模式

所以你的脚本应该更新如下。

请注意,这是一个不管理错误的快速解决方案!(又名error事件)


const status = require('net')
const util = require('util')

const hosts = [
  ['Server #1', 'google.com', 80],
  ['Server #2', 'jhfg87ed4.com', 80], // fake, just for response check
  ['Server #3', 'stackoverflow.com', 80]
]

function server (id, cb) {
  const host = hosts[id]
  const sock = new status.Socket()
  sock.setTimeout(2500)
  sock
    .on('connect', () => {
      cb(null, host[0] + ': Up.') // null as first parameter that is error
      sock.destroy()
    })
    .on('error', e => {
      cb(new Error(host[0] + ': Down: ' + e.message))
    })
    .on('timeout', e => {
      cb(new Error(host[0] + ' Down: timeout'))
    })
    .connect(host[2], host[1])
}

const serverPromise = util.promisify(server)

async function results () {
  let res = await serverPromise(0)
  console.log(res)
  try {
    res = await serverPromise(1)
    console.log(res)
  } catch (error) {
    console.log(error)
  }
  res = await serverPromise(2)
  console.log(res)
}

results()

推荐阅读