关于async函数和普通函数的疑问
发布于 9 年前 作者 varHarrie 6509 次预览 最后一次回复是 9 年前 来自 问答
根据我的了解async函数就是generator的封装,其本质是一个自执行的generator,并且执行返回一个promise。
co的yield/generator在运用上有一个致命的问题,所有用到yield的环境,必须用一个generator包裹,并且父层也必须使用这种方式,顶层调用时,需要使用co去封装,使其自执行。
那么async/await与yield/generator相比有什么优势吗?顶层调用一个async函数,可以当做普通函数调用?
最近在尝试整合koa v2和socket.io,koa路由就是用async/await方式,调用异步函数完成数据库查询,但是在socket.io上的请求,能不能使用async函数替换普通函数呢,如下: socket.io官方文档的写法:
io.on('connect', (socket) => {
socket.on('join', (roomId) => { // 这是一个普通函数
// 如果这里用到异步调用,或者调用promise,就需要使用callback或then方式
Room.findById(roomId).then((room) => {
console.log(room)
// 如果还有多次异步操作就会导致嵌套层数太深
...
socket.emit('success', room)
})
}
})
异步函数写法(这样写可行吗?)
io.on('connect', (socket) => {
socket.on('join', async (roomId) => { // 这是一个async函数
const room = await Room.findById(roomId).exec()
...
// 可能还有其他await异步调用
socket.emit('success', room)
}
})
写了一个测试,发现确实能够获得a和b两个promise的结果,那说明async函数可以不用await去调用吗?这样写会不会有什么问题?
const p = function (word, t) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(word + ' ' + t)
}, t)
})
}
socket.on('say', async () => {
const a = await p('aaa', 1000)
const b = await p('bbb', 3000)
console.log(a, b)
socket.emit('response', {a, b})
})
9 回复
目前v8还没有实现async/await(还有不少bug在调(link)) 将async转换成generator只不过是babel根据现有的能力转换而已
https://chromium.googlesource.com/v8/v8.git/+/d08c0304c5779223d6c468373af4815ec3ccdb84 这是5月份实现async原型的提交,粗略的看了一眼,内部是Promise
下面是目前的状态 Async/Await implementation in V8
不行的, 你在一个异步函数里面 throw 一个 error 试试, 只会导致返回的Promise 值被 reject, 采用Native Promise 实现的话, unhandle rejection 会悄无声息的被吞…
1 co里面可以yield promise和thunk 2
https://github.com/socketio/socket.io/issues/2638 这是老外的回复,他说可以,并且使用try/catch去处理异常
@magicdawn 所说的throw一个error,使promise被reject不就是想要的结果吗,想要处理unhandle rejection使用try/catch去处理才比较合理吧
@joesonw co确实是一种解决方案,但是已经上koa v2了,就不想再回头了 如果将async函数当做promise去用then和catch执行,那不还是异步的写法?无限嵌套…
既然已经用koa v2了, 希望能够有统一的一种写法(async/await)
@SinalVee 看来还要再等一段时间啊
@varHarrie socket.io 是事件的, 要自己包装下才可以.
@magicdawn 你说的是对的,这种
unhandle rejection在async function之外连try/catch都无法捕获,被吞了一点提示都没有,改用bluebird之后才有异常提示,但是函数外部依然无法捕获。@varHarrie