我正试图用async/await 简化代码
但是在制作具有异步/等待结构的https.get
时存在问题。
我知道如何使用第三方模块,但更喜欢本机node.jshttps
模块。
以下代码不适用于我:
async function get_page() {
const https = require('https')
const url = 'https://example.com'
const util = require('util')
const https_get = util.promisify(https.get)
const data = await https_get(url)
do_awesome_things_with_data(data)
}
此代码运行良好:
function get_page() {
const https = require('https')
const url = 'https://example.com'
let data = ''
https.get(url, res => {
res.on('data', chunk => { data += chunk })
res.on('end', () => {
do_awesome_things_with_data(data)
})
})
}
https.get
不会返回可承诺的内容,因为回调的签名与(err, value)
不匹配,所以您不能等待它。
但是,您可以像这样将https.get
调用封装在Promise中,然后在调用get_page
时等待
const https = require('https')
async function get_page() {
const url = 'https://example.com'
return new Promise((resolve) => {
let data = ''
https.get(url, res => {
res.on('data', chunk => { data += chunk })
res.on('end', () => {
resolve(do_awesome_things_with_data(data));
})
})
})
}
// usage
(async () => await get_page())()
编辑
我已经更新了我的答案,其中包含了https.get
无法承诺的注释,并将require('https')
移到了函数调用之外。
不要promisify,而是滚动自己的函数,或者使用第三方库。Promisify无法包装https.get
返回的内容。
// generic promise method for https
const requestPromise = ((urlOptions, data) => {
return new Promise((resolve, reject) => {
const req = https.request(urlOptions,
(res) => {
let body = '';
res.on('data', (chunk) => (body += chunk.toString()));
res.on('error', reject);
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode <= 299) {
resolve({statusCode: res.statusCode, headers: res.headers, body: body});
} else {
reject('Request failed. status: ' + res.statusCode + ', body: ' + body);
}
});
});
req.on('error', reject);
req.write(data, 'binary');
req.end();
});
});
然后这样称呼它:
async function get_page() {
const url = 'https://example.com'
const data = await requestPromise({url, method:'GET'})
do_awesome_things_with_data(data)
}
或者简单地使用axios
之类的库来返回本机promise,并处理其他样板案例。
以下是我的操作方法:
async myFunc = function {
let url = 'http://your.data/file';
let promise = new Promise((resolve, reject) => {
var data = '';
https.get(url, res => {
res.on('data', chunk => { data += chunk })
res.on('end', () => {
resolve(data);
})
})
});
let result = await promise; // wait until the promise resolves
doStuffWithResult(result);
};
在我的例子中,我获取了一个.json文件,所以我实际上使用了resolve(JSON.parse(data))
来返回干净的json对象。