我试图找到一些方法来编写我的一般promisify函数来使用async并等待socket.io
这是我的代码第一个未能完成而第二个成功没有问题。
这两者有什么区别?为什么第一个会失败?
function promisify (func) {
return new Promise((resolve, reject) => func(() => {
resolve()
console.log('closeServer')
}))}
async function timer1 () {
await Promise.resolve(promisify(server.close))
}
function closeServer () {
return new Promise((resolve, reject) => server.close(() => {
resolve()
console.log('closeServer')
}))}
async function timer2 () {
await Promise.resolve(closeServer())
}
让我告诉你们这些日志,
第二个
> nodemon src/index.js --exec babel-node --presets es2015
[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node src/index.js --presets es2015`
Server listening at port 3000
^C(node:28061) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): TypeError: Cannot read property '_handle' of undefined
(node:28061) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
第二个
> nodemon src/index.js --exec babel-node --presets es2015
[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node src/index.js --presets es2015`
Server listening at port 3000
^CcloseServer
答案 0 :(得分:0)
你的第一个立即调用该函数,当它被回调时,用undefined
解析。传递数据或处理错误没有任何作用;实际上,如果if (false)
并非总是如此,那么在尝试获取ReferenceError
标识符的值时,代码会因err
而失败。
如果你想编写一个将Node风格的回调API转换为启用promise的API的函数,那就相当简单了。您假设回调是函数在其参数列表中所期望的最后一个,并且它使用通常的err, data
参数调用回调:
const promisify = func => (...args) => new Promise((resolve, reject) => {
func(...args, (err, data) => {
if (err) {
reject(err instanceof Error ? err : new Error(err));
} else {
resolve(data);
}
});
});
它返回一个函数,当调用它时,将调用原始文件传递其所有参数以及最后的回调,并返回一个promise。当回调被调用时,它假定它采用通常的err, data
格式并拒绝承诺,如果err
是真实的,否则解决它。它确保拒绝是Error
(我的偏好总是使用Error
throw
和reject
;您的风格可能会有所不同。)
用法:
const readFileP = promisify(fs.readFile);
然后你想在哪里使用结果:
readFileP("filename", "utf-8")
.then(data => { /* ... */ })
.catch(err => { /* ... */ });
然而,如果您进行搜索,那么有一些功能丰富的库可以为您提供更大的灵活性,并且也会进行测试。