Невозможно получить исходное возвращаемое значение обещанной функции - PullRequest
0 голосов
/ 20 февраля 2019

Код ниже работает, но он не обещан.

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, чтобы я мог закрыть сервер.

Кто-нибудь может определить, что здесь происходит, и как я могу получить желаемое поведение?

1 Ответ

0 голосов
/ 21 февраля 2019

[Перезапись, потому что здесь происходит несколько вещей]

Поработав над этим кодом немного, я понял, что было несколько проблем / ошибочных предположений, а именно:

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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...