简体   繁体   English

使用.net.connect时回调和promise的区别

[英]Difference between callback and promise when using `net.connect`

I've built a simple script to detect if a port is opened/closed on my machine.我已经构建了一个简单的脚本来检测端口是否在我的机器上打开/关闭。 I've successfully make it work using the old-fashion callback way, but can't make it work with Promise (async/await).我已经成功地使用老式回调方式使其工作,但无法使其与 Promise(异步/等待)一起工作。

Any clue why the two scripts below are not working exactly the same?任何线索为什么下面的两个脚本不完全相同? Using callbacks, it works neat.使用回调,它工作得很好。 Using Promise (async/await) it crash by throwing an "uncaughtException" error.使用 Promise (async/await) 它通过抛出“uncaughtException”错误而崩溃。

✅ Using callbacks ✅ 使用回调

const net = require('node:net')

/**
 * Connect to port with callback
 */

function connectToPort(port, callback) {
  const client = net.connect(port, 'localhost', function () {
    callback(true)
  })

  client.on('error', function (err) {
    callback(err)
  })
}

/**
 * Connect
 */

async function test(port) {
  console.log(`Trying to connect to port "${port}"...`)

  // Connect with callback
  connectToPort(port, function (result) {
    console.log({ port, open: result === true })
  })
}

// Output:
// Trying to connect to port "4242"...
// { port: 4242, open: false }
test(4242)

❌ Using Promise (async/await) ❌ 使用 Promise(异步/等待)

const net = require('node:net')

/**
 * Connect to port with Promise
 */

function asyncConnectToPort(port) {
  return new Promise(function (resolve, reject) {
    const client = net.connect(port, 'localhost', function () {
      resolve(true)
    })

    client.on('error', function (err) {
      reject(err)
    })
  })
}

/**
 * Connect
 */

async function test(port) {
  console.log(`Trying to connect to port "${port}"...`)

  // Connect with promise
  const result = await asyncConnectToPort(port)
  console.log({ port, open: result === true })
}

// Output:
// Trying to connect to port "4242"...
// Error: connect ECONNREFUSED 127.0.0.1:4242
test(4242)

Both scripts look exactly the same to me.这两个脚本在我看来完全一样。 Apparently, the "error" event must be present to avoid Nodejs to throw an "uncaughtException".显然,必须存在“error”事件以避免 Nodejs 抛出“uncaughtException”。 That "special" event is detected when using callback, but I suspect it's not with Promise. Could it be something behind the scene that differs when working with await/async script?使用回调时会检测到该“特殊”事件,但我怀疑它与 Promise 无关。在使用 await/async 脚本时,它可能是幕后不同的东西吗?

An error event is raised in both your code examples.在您的两个代码示例中都会引发错误事件

In the Promise code that you wrote you pass that error event to reject() .您编写的 Promise 代码中,您将该错误事件传递给reject()

When you call reject you raise an exception.当您调用reject时,您会引发异常。

Hence, you get an exception in your Promise based code but not in the other code.因此,您在基于 Promise 的代码中会遇到异常,但在其他代码中不会。 You added one!你加了一个! . .

Handling it is a case of:处理它是一种情况:

try {
  const result = await asyncConnectToPort(port)
  console.log({ port, open: result === true })
} catch (e) {
  // do something with e here
}

However a Promise can only be settled once .但是一个Promise只能结算一次

The code you've written will call resolve when the callback to net.connect runs and it will call reject on an error event but these are not mutually exclusive.您编写的代码将在net.connect的回调运行时调用resolve ,并且它将在错误事件上调用reject ,但这些并不相互排斥。

It's possible for your code to end up calling both resolve and reject , and also for it to call reject multiple times.您的代码有可能最终同时调用resolvereject ,也有可能多次调用reject

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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