Async: `async` 功能支持

创建于 2017-03-16  ·  10评论  ·  资料来源: caolan/async

房间里的大象之一是对 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没有意义。 大多数控制流方法(除了autoqueue之类的东西)更容易使用本机控制流构造进行复制。 mapparallel可以替换为Promise.mapPromise.all 。 但是,限制收集功能以及auto和其他一些功能将非常有用。 (另外,带有async函数的autoInject #$ 是异步控制流的梦想!)

enhancement feedback-wanted

最有用的评论

有理由做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,这样它才会起作用——让用户去做。

所有10条评论

我将对此进行更多思考,但我想问几个技术问题,以便我可以尝试更好地设想这看起来像什么..

有理由做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 ,因为conn1conn2undefined 。 改成之后

async.autoInject({
    conn1: async function () {
      return 'foo'
    },
    conn2: async function () {
      return 'bar'
    },
})

它工作正常。 但是,我们不支持转译的async函数。 你在编译你的代码吗?

此页面是否有帮助?
0 / 5 - 0 等级