私の機能は、httpサーバーが起動するとすぐに解決する約束を解決します。これは私のコードです:
function start() {
return new Promise((resolve, reject) {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
}
開始機能を非同期/待機に変換するにはどうすればよいですか?
関数宣言の前にasync
を、await
コンストラクターにPromise
を含めます。ただし、本質的には既存のパターンにコードを追加することになります。 await
は値をPromise
に変換しますが、質問のコードは既にPromise
コンストラクターを使用しています。
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));
この場合、他の回答が示唆するように_new Promise
_を作成するとうまくいきますが、一般的な規則として til.promisify は同じことを何度も書くのを止めることができます。
そのため、代わりに次のようなことができます:(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)
は、通常コールバックを受け入れる関数を取り、代わりにプロミスを返すこの関数の新しいラップされたバージョンを返します。
詳細な手順:
_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);
_
bluebird を使用すると、より高度な約束をすることができます。
これは、http
server listen
関数を真に約束しようとしたときにつまずいたものです。最大の問題は、listening
コールバックで解決するのではなく、起動時にエラーを処理することです。
Node.jsサーバー、catch
、または派生net
/http
は、https
インスタンスであるため、PromiseでラップしてEventEmitter
(他の回答が示唆するように)またはtry-catchブロックを試みても効果はありません。代わりに、error
イベントとして発行されます。
したがって、上記のすべてを考慮すると、約束されたサーバーlisten
関数の正しい実装は次のとおりです。
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);
});
}
ハンドラー内の呼び出しを拒否および解決することは、リスナースタックの先頭に追加され、相互にキャンセルします(最初に起動したユーザー)。
そうすれば、listen
メソッドがサーバーを起動するか、キャッチ可能なエラーをスローすることが保証されます。
const doRequest = () => new Promise((resolve, reject) {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
async function start() {
await doRequest()
}
こんな感じ
私は基本的なユーティリティを作成しました最も適切な方法ではないかもしれませんしかし、方法ですより読みやすい 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;
}
これが基本的な概念です。ただし、carrefulで、promiseが未定義の値を返す可能性がある場合、関数は永久に実行されます(ただし、これはクラッシュしません)。