下面的代码可以工作,但没有 promise 。
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
我试图解决的问题是我想用依赖于服务器运行的代码替换“做一些事情”日志,并且监听回调(打印“正在监听”)已被调用。正如您所看到的,“做一些事情”记录在“正在收听”之前。 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 对象,这样我就可以关闭服务器。
任何人都可以确定这里发生了什么,以及我如何获得我想要的行为?
最佳答案
[重写,因为这里发生了很多事情]
在对这段代码进行了一些研究之后,我意识到存在几个问题/错误的假设,如下所示:
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();
如果您想 Promisify 使其与 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));
关于javascript - 无法获取 promise 函数的原始返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54795136/