[英]How do I delay an array callback using async/await in JavaScript?
[英]How do i wrap a callback with async await?
我的函數返回一個承諾,該承諾在 http 服務器啟動后立即解決。 這是我的代碼:
function start() {
return new Promise((resolve, reject) {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
}
如何將 start 函數轉換為 async/await?
在函數聲明之前包含async
並await
Promise
構造函數。 請注意,您實際上是在向現有模式添加代碼。 await
將值轉換為Promise
,盡管 Question 中的代碼已經使用了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
工作正常,但作為一般規則, util.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);
更高級的promisification 可以用bluebird完成。
const doRequest = () => new Promise((resolve, reject) {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
async function start() {
await doRequest()
}
我相信這樣的事情
這是我在嘗試使http
服務器listen
功能真正承諾時偶然發現的。 最大的問題不是解決listening
回調,而是處理啟動時的錯誤。
包裝在 Promise 中並嘗試catch
(如其他答案所建議的)或 try-catch 塊不會產生任何效果,因為任何 Node.js 服務器、 net
或派生的http
/ https
都是EventEmitter
實例,這意味着不會引發錯誤。 相反,它們作為error
事件發出。
因此,考慮到以上所有因素,promisified server 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
方法要么啟動服務器,要么拋出可捕獲的錯誤。
我創建了一個基本的實用程序,它可能不是最合適的方法,但在 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;
}
這是基本概念。 但是,如果您的承諾可能返回未定義的值,則要小心,因為該函數將永遠運行(但這不會崩潰)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.