下面的代码可以工作,但是不能保证。
const express = require('express');
function listenAndReturnServer() {
app = express();
console.log('Before listen');
const server = app.listen(8001, function() {
console.log('Now listening');
});
console.log('After listen');
return server;
}
const server = listenAndReturnServer();
console.log('Doing some stuff');
console.log(typeof(server));
它输出以下内容:
Before listen
After listen
Doing some stuff
object
Now listening
我要解决的问题是我想用依赖于服务器运行的代码替换“执行一些操作”日志,并调用了listen回调(显示“ Now Listening”)。如您所见,“正在监听”之前会记录“做一些事情”。进来util.promisify。
我已将以上内容更改为以下内容。
const express = require('express');
const util = require('util');
async function listenAndReturnServer() {
app = express();
console.log('Before listen');
const listenAsync = util.promisify(app.listen);
const server = await listenAsync(8001).then(() => {
console.log('Now listening');
});
console.log('After listen');
return server;
}
async function main() {
const server = await listenAndReturnServer();
console.log('Doing some stuff');
console.log(typeof(server));
}
main();
这一次,事物至少以正确的顺序登录。
Before listen
Now listening
After listen
undefined
Doing some stuff
现在有一个新问题:server
的类型未定义。实际上,我需要它是原始的Server对象,因此我可以关闭服务器。
任何人都可以识别这里发生的事情以及如何获得想要的行为吗?
答案 0 :(得分:2)
[正在重写,因为这里发生了很多事情]
在这段代码上工作了一段时间之后,我意识到存在以下几个问题/错误的假设:
const express = require('express');
const util = require('util');
async function listenAndReturnServer() {
app = express();
console.log('Before listen');
// ISSUE #1: `listenAsync` is not bound to `app` here. This
// risks errors where Express may rely on `this` internally.
//
// ISSUE #2: Promisify is intended to operate on methods that
// take node-style callbacks, where the *callback* receives
// (err, arg0, arg1, ...) arguments, with the promise
// resolving to the 2nd argument (arg0).
// In the case of listen(), though, the callback isn't expected
// to be node-style(!), so doesn't receive any arguments
// (see https://nodejs.org/api/net.html#net_server_listen)
const listenAsync = util.promisify(app.listen);
// ISSUE #3: `await` and `then()` serve similar purposes.
// Using them together like this is a little weird.
// You should probably just `await`, then do your console.log
// afterwards.
const server = await listenAsync(8001).then(() => {
console.log('Now listening');
});
console.log('After listen');
return server;
}
async function main() {
const server = await listenAndReturnServer();
console.log('Doing some stuff');
console.log(typeof(server));
}
main();
如果您要对此进行承诺以使其与async
配合使用,则这样简单地创建一个Promise
可能会更简单:
const express = require('express');
const app = express();
// Note: Not writing this as an `async` function because none
// of the APIs we're using return promises that can be `await`ed,
// and we explicitly return a promise
function main() {
return new Promise(function(resolve, reject) {
// Resolve to the server instance if listen() succeeds
// Note: `server` here is Node's `http` server, not the Express instance
const server = app.listen(8001, () => resolve(server));
// Otherwise reject promise if there's an error
server.on('error', reject);
});
}
main()
.then(server => console.log(server))
.catch(err => console.error(err));