房间里的大象之一是对 Node 和 Chrome 的新async
/ await
支持,并且很快就会出现在所有其他主要浏览器中。 我一直在思考 Async 在async
/ await
世界中可以做什么。
目前,我们可以通过使用asyncify
包装async
函数来调整它们。 由于async
函数本质上只是一个返回 Promise 的函数,因此旧适配器可以轻松地将其转换为回调样式函数。 然而,它导致看起来有些荒谬:
async.mapLimit(arr, 10, async.asyncify(async (val) => {
let foo = await doSomething(val);
//...
return bar;
}), done);
但是, async
函数的规范中的功能之一是:
Object.getPrototypeOf(asyncFn)[Symbol.toStringTag] === "AsyncFunction"
这提供了一种轻松检测(本机) async
函数的方法。 我们可以使用这种技术来自动asyncify
他们。 上面的例子变成:
async.mapLimit(arr, 10, async (val) => {
let foo = await doSomething(val);
//...
return bar;
}, done);
...这似乎更自然地流动。 我也认为我们应该继续使用回调。 如果用户想要await
结果,他们将不得不promisify
函数,或pify
整个异步:
let result = await pify(async.mapLimit)(arr, 10, async (val) => {
let foo = await doSomething(val);
//...
return bar;
});
上述检测async
函数的方法仅适用于原生函数。 我认为没有办法检测 Babel 转译函数。 我们当然不能检测到只返回 Promises 的普通函数,因为我们必须追溯不传递回调。 他会有一个巨大的警告,这只能在非常现代的环境中没有转译器的情况下工作,否则你仍然必须手动包装asyncify
。
此外,不可否认,许多 Async 方法对async
/ await
没有意义。 大多数控制流方法(除了auto
和queue
之类的东西)更容易使用本机控制流构造进行复制。 map
和parallel
可以替换为Promise.map
和Promise.all
。 但是,限制收集功能以及auto
和其他一些功能将非常有用。 (另外,带有async
函数的autoInject
#$ 是异步控制流的梦想!)
我将对此进行更多思考,但我想问几个技术问题,以便我可以尝试更好地设想这看起来像什么..
有理由做Object.getPrototypeOf(asyncFn)[Symbol.toStringTag] === "AsyncFunction"
还是我们可以做asyncFn[Symbol.toStringTag] === "AsyncFunction"
(似乎在FF中工作)?
每当有人提供格式cb(err, arg)
的回调时,提案也是如此,我们应该检测它是否是AsyncFunction
; 如果它是一个异步函数,我们应该应用promisify
否则按原样使用它
也很抱歉,我没有关注 await 示例,如果我们检测到该函数是AsyncFunction
支持await
的挑战是什么?
有理由做
Object.getPrototypeOf(asyncFn)[Symbol.toStringTag] === "AsyncFunction"
还是我们可以做asyncFn[Symbol.toStringTag] === "AsyncFunction"
(似乎在FF中工作)?
这只是规范的 ECMA 规范方法。 我想理论上,有人可以覆盖asyncFn[Symbol.toStringTag]
。
每当有人提供格式为 cb(err, arg) 的回调时,提案也是如此,我们应该检测它是否是 AsyncFunction; 如果它是一个异步函数,我们应该应用 promisify 否则按原样使用它
我觉得你有点倒退了。 无论我们在哪里接受一个接受回调的迭代函数( function(args..., callback) {}
),我们都应该检查它是否是一个async
函数,然后asyncify
它。
await
示例是如果有人想要await
一个异步方法会做的事情。 我认为我们不应该让 Async 方法开始返回 Promise,这样它才会起作用——让用户去做。
在#1390 中实现!
这是一个突破性的变化,破坏了我们部署的代码。 在不增加主版本的情况下做这些事情时请三思。
PS:感谢您使用此库所做的所有出色工作😄
射击! 什么破了。 您能否创建一张包含详细信息的票
这不起作用的环境?
谢谢!
2017 年 4 月 5 日星期三上午 10:18 曼努埃尔·瓦尔斯·费尔南德斯 <
通知@github.com> 写道:
这是一个突破性的变化,破坏了我们部署的代码。 请三思而后行
在不增加主要版本的情况下做这样的事情。PS:感谢您使用此库所做的所有出色工作😄
—
您收到此消息是因为您发表了评论。
直接回复此邮件,在 GitHub 上查看
https://github.com/caolan/async/issues/1386#issuecomment-291875817或静音
线程
https://github.com/notifications/unsubscribe-auth/ADUIEPNkTSOVuuiwucBVrH983X6B568Wks5rs6K3gaJpZM4Mf64R
.
同意,它也破坏了我的构建......
调用几天前工作的异步函数的瀑布开始失败,并出现“cb 不是函数”,因为不再向函数提供异步回调。
抱歉,我们破坏了您的代码。 我们没有预料到您会使用async
函数。 我建议回滚到 2.2.0,或者将代码重构为return
所需的值,而不是使用回调。 不幸的是,有了这个功能,猫已经出局了,所以我们无法回滚。
@aearly请不要提及它! 你真的很高兴回答:1st_place_medal:
@manvalls 向我暗示了一个不需要回滚的好解决方案。 当您使用符号来检测函数声明中的async
时,他想到了一个巧妙的方法来欺骗检测。
我的瀑布使用从其他模块导出的函数,其中一个是async
一个,因此导致失败。
因此,只需从以下更改:
...
/* services module */
function doThis(param, cb) {
...
}
async function doThatAsync(param, cb) {
...
}
module.exports = {
doThis: doThis,
doThat: doThatAsync
};
...
async.waterfall([
services.doThis,
services.doThat, // fails with "cb is not a function"
], err => {
...
}
到:
...
/* services module */
function doThis(param, cb) {
...
}
async function doThatAsync(param, cb) {
...
}
module.exports = {
doThis: doThis,
doThat: (...args) => doThatAsync(..args) // cheating the detection
};
...
async.waterfall([
services.doThis,
services.doThat, /* it works!!! */
], err => {
...
}
再一次非常感谢你
我们可以将 async/await 与 async.autoInject() 一起使用吗?
async.autoInject({
conn1: async function () {
return conn1;
},
conn2: async function () {
return conn2;
},
});
似乎不起作用,我得到:
错误:自动注入任务函数需要显式参数。
在 /Users/alexamil/WebstormProjects/nabisco/cdt-now/node_modules/async/dist/async.js:2081:23
在 /Users/alexamil/WebstormProjects/nabisco/cdt-now/node_modules/async
@ORESoftware是的, async
函数应该与autoInject
一起使用。 我测试了您在 Chrome 中发布的代码,它运行了。 我在最后的回调中得到了ReferenceError
,因为conn1
和conn2
是undefined
。 改成之后
async.autoInject({
conn1: async function () {
return 'foo'
},
conn2: async function () {
return 'bar'
},
})
它工作正常。 但是,我们不支持转译的async
函数。 你在编译你的代码吗?
最有用的评论
这只是规范的 ECMA 规范方法。 我想理论上,有人可以覆盖
asyncFn[Symbol.toStringTag]
。我觉得你有点倒退了。 无论我们在哪里接受一个接受回调的迭代函数(
function(args..., callback) {}
),我们都应该检查它是否是一个async
函数,然后asyncify
它。await
示例是如果有人想要await
一个异步方法会做的事情。 我认为我们不应该让 Async 方法开始返回 Promise,这样它才会起作用——让用户去做。