我已经使用 Babel 有一段时间了,我很喜欢它。但是,在主页上,它列出了支持的功能,它说Async functions
。
我已经做了很多谷歌搜索,我似乎只能理解它是 ES7 的一个特性。
请问什么是 ES7 异步函数?
我已经使用 Babel 有一段时间了,我很喜欢它。但是,在主页上,它列出了支持的功能,它说Async functions
。
我已经做了很多谷歌搜索,我似乎只能理解它是 ES7 的一个特性。
请问什么是 ES7 异步函数?
异步等待与 ES6 Promises 一起工作。您可以将它们视为使用 Promises 编写类似同步代码的一种方式。
async
关键字标记为将进行异步调用的方法。await
关键字标记实际调用。
使用 Promise,您需要将方法传递给 Promise 的方法.then()
来处理结果。
function doSomethingAsync() {
return new Promise((resolve, reject) => {
// call Rest service and resolve here
})
}
function printResult() {
doSomethingAsync()
.then(result => console.log(result));
}
这一切都很好。Async/Await
我们可以写最后一个函数有点不同。
async function printResult() {
let result = await doSomethingAsync();
console.log(result);
}
这样做的好处是它只是减少了对回调的需求。
有关更多信息,请参阅:https ://www.twilio.com/blog/2015/10/asyncawait-the-hero-javascript-deserved.html
ES2016(通常称为 ES7 或 ECMAScript 7)是 ECMA-262 标准(通常称为 JavaScript)的下一次演进,目前仍处于早期阶段。
异步函数是一种新的 JavaScript 功能,作为 ES2016 标准的一部分提出,尚未被任何浏览器支持。它们建立在promises之上。
请参阅下面的各种权威来源对这一新功能的介绍。
尽管 Async 函数通常被称为ES7 asynch functions
(例如,为了消除它们与async.js或一般的异步 JavaScript的歧义),但Axel Rauschmayer建议不要将它们称为 ,因为只有在下一个标准提出后才会将其包含在下一个标准中。已经到了第四阶段。
异步函数目前仅处于第 3 阶段。事实上,ES2016 可能不会包含异步函数(正如Felix Kling在下面的评论中指出的那样)。
从第 3 阶段提案:
介绍
在 ECMAScript 中引入 Promise 和生成器为显着改进在 ECMAScript 中编写异步代码的语言级模型提供了机会。
在 ES6 讨论期间,对Deferred Functions提出了类似的提议。这里的提议支持相同的用例,使用相似或相同的语法,但直接建立在与生成器平行的控制流结构上,并使用承诺作为返回类型,而不是定义自定义机制。
该提案的开发工作在 https://github.com/tc39/ecmascript-asyncawait进行。请在那里提出问题。重要的贡献仅限于 TC39 成员,但欢迎并鼓励对小问题提出拉取请求!
该提案的状态
该提案于 2015 年 9 月被接受进入 ECMAScript规范流程的第 3 阶段(“候选者”)。支持者打算在 11 月底之前将该提案接受进入第 4 阶段(“完成”)。
例子
举个例子,首先使用 Promises 编写。该代码将一组动画链接到一个元素上,当动画中出现异常时停止,并返回最终成功执行的动画产生的值。
function chainAnimationsPromise(elem, animations) { let ret = null; let p = currentPromise; for(const anim of animations) { p = p.then(function(val) { ret = val; return anim(elem); }) } return p.catch(function(e) { /* ignore and keep going */ }).then(function() { return ret; }); }
已经有了 Promise,代码比直接回调风格有了很大改进,这种循环和异常处理具有挑战性。
Task.js和类似的库提供了一种使用生成器的方法来进一步简化保持相同含义的代码:
function chainAnimationsGenerator(elem, animations) { return spawn(function*() { let ret = null; try { for(const anim of animations) { ret = yield anim(elem); } } catch(e) { /* ignore and keep going */ } return ret; }); }
这是一个显着的改进。所有超出代码语义内容的 Promise 样板都被删除,内部函数的主体代表用户意图。然而,有一个样板的外层将代码包装在一个额外的生成器函数中,并将其传递给一个库以转换为一个 Promise。这个层需要在每个使用这种机制来产生承诺的函数中重复。这在典型的异步 Javascript 代码中很常见,因此消除对剩余样板的需求是有价值的。
使用异步函数,所有剩余的样板都被删除,只在程序文本中留下语义上有意义的代码:
async function chainAnimationsAsync(elem, animations) { let ret = null; try { for(const anim of animations) { ret = await anim(elem); } } catch(e) { /* ignore and keep going */ } return ret; }
来自Jake Archibald的文章ES7 异步函数:
与承诺异步
在关于 promises 的 HTML5Rocks 文章中,最后一个示例展示了如何为故事加载一些 JSON 数据,然后使用它为章节获取更多 JSON 数据,然后在章节到达后立即按顺序呈现章节。
代码如下所示:
function loadStory() { return getJSON('story.json').then(function(story) { addHtmlToPage(story.heading); return story.chapterURLs.map(getJSON) .reduce(function(chain, chapterPromise) { return chain.then(function() { return chapterPromise; }).then(function(chapter) { addHtmlToPage(chapter.html); }); }, Promise.resolve()); }).then(function() { addTextToPage("All done"); }).catch(function(err) { addTextToPage("Argh, broken: " + err.message); }).then(function() { document.querySelector('.spinner').style.display = 'none'; }); }
不错,但是……</p>
这次使用 ES7 异步函数……</h3>
async function loadStory() { try { let story = await getJSON('story.json'); addHtmlToPage(story.heading); for (let chapter of story.chapterURLs.map(getJSON)) { addHtmlToPage((await chapter).html); } addTextToPage("All done"); } catch (err) { addTextToPage("Argh, broken: " + err.message); } document.querySelector('.spinner').style.display = 'none'; }
使用异步函数(完整提案),您可以
await
兑现承诺。这会以非阻塞方式停止函数,等待 promise 解析并返回值。如果 promise 拒绝,它会抛出拒绝值,因此您可以使用catch
.编辑:我最初
await
在箭头函数中使用,显然这是不允许的,所以我用for
循环替换了它。Domenic 让我了解了为什么await
不能在箭头函数中使用。
loadStory
返回一个承诺,因此您可以在其他异步函数中使用它。(async function() { await loadStory(); console.log("Yey, story successfully loaded!"); }());
发电机/产量
JavaScript 生成器是一个相对较新的概念,它们是在 ES6(也称为 ES2015)中引入的。
当你执行你的函数时,你可以在任何时候暂停它,计算其他东西,做其他事情,然后返回它,即使有一些值并继续,这不是很好吗?
这正是生成器函数为您所做的。当我们调用生成器函数时,它不会开始运行,我们将不得不手动迭代它。
function* foo () { var index = 0; while (index < 2) { yield index++; } } var bar = foo(); console.log(bar.next()); // { value: 0, done: false } console.log(bar.next()); // { value: 1, done: false } console.log(bar.next()); // { value: undefined, done: true }
如果你想轻松地使用生成器来编写异步 JavaScript,你也需要co。
Co 是一个基于生成器的 Node.js 和浏览器控制流,使用 Promise,让你以一种不错的方式编写非阻塞代码。
使用
co
,我们之前的示例可能如下所示:co(function* (){ yield Something.save(); }).then(function() { // success }) .catch(function(err) { //error handling });
你可能会问:并行运行的操作呢?答案比您想象的要简单(实际上它只是一个
Promise.all
):yield [Something.save(), Otherthing.save()];
异步/等待
异步函数是在 ES7 中引入的——目前只能使用像 babel 这样的编译器。(免责声明:现在我们谈论的是 async 关键字,而不是 async 包)
简而言之,使用
async
关键字,我们可以使用 和 生成器的组合来做我们正在做的事情co
- 除了黑客攻击。使用Promises
async
的底层函数——这就是为什么 async 函数会返回一个Promise
.