web-dev-qa-db-de.com

Wie wickle ich einen Rückruf mit async erwarten?

Meine Funktion löst ein Versprechen auf, das gelöst wird, sobald der http-Server gestartet wird. Das ist mein Code:

function start() {
    return new Promise((resolve, reject) {
        this.server = Http.createServer(app);
        this.server.listen(port, () => {
            resolve();
        });
    })
}

Wie kann ich die Startfunktion in asynchron/warten konvertieren? 

7
Tiago Bértolo

Fügen Sie async vor der Funktionsdeklaration und await den Promise-Konstruktor ein. Beachten Sie jedoch, dass Sie im Wesentlichen dem vorhandenen Muster Code hinzufügen. await konvertiert einen Wert in eine Promise, obwohl der Code in Question Promise-Konstruktor bereits verwendet.

async function start() {
    let promise = await new Promise((resolve, reject) => {
        this.server = Http.createServer(app);
        this.server.listen(port, () => {
            resolve();
        });
    })
    .catch(err => {throw err});

    return promise
}

start()
.then(data => console.log(data))
.catch(err => console.error(err));
7
guest271314

Wenn Sie einen new Promise wie die anderen Antworten erstellen, ist dies in diesem Fall gut, aber in der Regel kann util.promisify Sie verhindern, dass Sie dasselbe oft schreiben. 

So können Sie stattdessen etwas tun: (node.js v8.0.0 +)

const util = require('util');
async function start() {
    let server = Http.createServer(app);
    await util.promisify(server.listen.bind(server))(port);
}

util.promisify(some_function) nimmt eine Funktion, die normalerweise einen Rückruf akzeptiert, und gibt eine neue, umschlossene Version dieser Funktion zurück, die stattdessen ein Versprechen zurückgibt.

Mit mehr erklärten Schritten:

let server = Http.createServer(app);
// .bind() is needed so that .listen() keeps the correct `this` context when it is called.
// If your function does not require any specific context, leave off .bind()
let listen_promise = util.promisify(server.listen.bind(server));
await listen_promise(port);

Weitergehende Versprechungen können mit bluebird durchgeführt werden.

3
JoshWillik
const doRequest = () => new Promise((resolve, reject) {
        this.server = Http.createServer(app);
        this.server.listen(port, () => {
            resolve();
        });
    })

async function start() {
 await doRequest()
}

so etwas glaube ich

2
Kejt

Dies ist etwas, worüber ich gestolpert bin, als ich versuche, die http server listen-Funktion wirklich zu versprechen. Das größte Problem besteht nicht darin, listening callback zu lösen, sondern die Fehler beim Start zu behandeln.

Das Umwickeln in Promise und der Versuch, catch (wie andere Antworten vermuten lassen) oder Try-Catch-Block haben keine Auswirkungen, da alle Server, net oder abgeleiteten http/https-Instanzen EventEmitter sind. Sie werden stattdessen als error-Ereignis ausgegeben.

In Anbetracht all der obigen Punkte lautet die korrekte Implementierung der listen-Funktion des zugesagten Servers wie folgt:

const { createServer } = require('http');

const server = createServer();

const listen = async (port, Host) => {
  return new Promise((resolve, reject) => {
    const listeners = {};

    listeners.onceError = (error) => {
      server.removeListener('listening', listeners.onceListening);
      reject(error);
    };

    listeners.onceListening = () => {
      server.removeListener('error', listeners.onceError);
      resolve();
    };

    server
      .prependOnceListener('error', listeners.onceError)
      .prependOnceListener('listening', listeners.onceListening);

    server.listen(port, Host);
  });
}

Ablehnungs- und Auflösungsaufrufe innerhalb von Handlern werden dem Listener-Stack vorangestellt und stornieren sich gegenseitig - wer zuerst feuert.

Auf diese Weise wird garantiert, dass die listen-Methode den Server startet oder einen abfangbaren Fehler ausgibt.

1
Damaged Organic

Ich habe eine grundlegende Funktion erstellt, die möglicherweise nicht die geeignetste Methode ist aber so besser lesbar IMO:

// async timout util
const timeout = async ms => new Promise(res => setTimeout(res, ms));

async function start() {
    let output;

    this.server = Http.createServer(app);
    this.server.listen(port, () => {
        output = true; // or can be any data that you want to return
    });
    while (output === undefined) await timeout(10);
    return output;
}

Dies ist das Grundkonzept. Sei jedoch carreful Wenn dein Versprechen undefinierte Werte zurückgibt, wird die Funktion für immer ausgeführt (dies wird jedoch nicht abstürzen).

0
538ROMEO