ES2017异步函数现已正式可用

ES2017标准已于2017年6月份正式定稿了,并普遍支持最新的特性:异步函数。若是你曾经被异步 JavaScript 的逻辑困扰,这么新函数正是为你设计的。css

异步函数或多或少会让你编写一些顺序的 JavaScript 代码,可是却不须要在 callbacks、generators 或 promise 中包含你的逻辑。前端

以下代码:api

function logger() {promise

let data = fetch('http://sampleapi.com/posts')
console.log(data)

}
logger()
这段代码并未实现你的预期。若是你是在JS中编写的,那么你可能会知道为何。浏览器

下面这段代码,却实现了你的预期。异步

async function logger() {async

let data = await fetch('http:sampleapi.com/posts')
console.log(data)

}
logger()
这段代码起做用了,从直观上看,仅仅只是多了 async 和 await 两个词。ide

ES6 标准以前的 JavaScript 异步函数

在深刻学习 async 和 await 以前,咱们须要先理解 Promise。为了领会 Promise,咱们须要回到普通回调函数中进一步学习。函数

Promise 是在 ES6 中引入的,并促使在编写 JavaScript 的异步代码方面,实现了巨大的提高。今后编写回调函数再也不那么痛苦。工具

回调是一个函数,能够将结果传递给函数并在该函数内进行调用,以便做为事件的响应。同时,这也是JS的基础。

function readFile('file.txt', (data) => {

// This is inside the callback function
console.log(data)

}
这个函数只是简单的向文件中记录数据,在文件完成以前进行读取是不可能的。这个过程彷佛很简单,可是若是想要按顺序读取并记录五个不一样的文件,须要怎么实现呢?

没有 Promise 的时候,为了按顺序执行任务,就须要经过嵌套回调来实现,就像下面的代码:

// This is officially callback hell
function combineFiles(file1, file2, file3, printFileCallBack) {

let newFileText = ''
readFile(string1, (text) => {
    newFileText += text
    readFile(string2, (text) => {
        newFileText += text
        readFile(string3, (text) => {
            newFileText += text
            printFileCallBack(newFileText)
        }
    }
}

}
这就很难推断函数下面会发生什么,同时也很难处理各类场景下发生的错误,好比其中某个文件不存在的状况。

Promise 改善了这种状况

这正是 Promise 的优点所在,Promise 是对还未产生的数据的一种推理。Kyle Simpson 将 Promise 解释为:就像在快餐店里点餐同样。

  • 点餐
  • 为所点的午饭付费,并拿到排队单号
  • 等待午饭
  • 当你的午饭准备好了,会叫你的单号提醒你取餐
  • 收到午饭

正如上面的这种场景,当你等餐时,你是没法吃到午饭的,可是你能够提早为吃午饭作好准备。你能够进行其它事情,此时你知道午饭就要来了,虽然此刻你还没法享用它,可是这个午饭已经“promise”给你了。这就是所谓的 promise,表示一个最终会存在的数据的对象。

readFile(file1)

.then((file1-data) => { /* do something */ })
.then((previous-promise-data) => { /* do the next thing */ })
.catch( /* handle errors */ )

上面是 Promise 语法。它主要的优势就是能够将队列事件以一种直观的方式连接在一块儿。虽然这个示例清晰易懂,可是仍是用到了回调。Promise 只是让回调显得比较简单和更加直观。

最佳方式:async / await

若干年前,async 函数归入了 JavaScript 生态系统。就在上个月,async 函数成为了 JavaScript 语言的官方特性,并获得了普遍支持。

async 和 await 是创建在 Promise 和 generator上。本质上,容许咱们使用 await 这个关键词在任何函数中的任何咱们想要的地方进行暂停。

async function logger() {

// pause until fetch returns
let data = await fetch('http://sampleapi.com/posts')
console.log(data)

}
上面这段代码运行以后,获得了想要的结果。代码从 API 调用中记录了数据。

这种方式的好处就是很是直观。编写代码的方式就是大脑思考的方式,告诉脚本在须要的地方暂停。

另外一个好处是,当咱们不能使用 promise 时,还可使用 try 和 catch:

async function logger () {

try {
    let user_id = await fetch('/api/users/username')
    let posts = await fetch('/api/`${user_id}`')
    let object = JSON.parse(user.posts.toString())
    console.log(posts)
} catch (error) {
    console.error('Error:', error)
}

}
上面是一个刻意写错的示例,为了证实了一点:在运行过程当中,catch 能够捕获任何步骤中发生的错误。至少有三个地方,try 可能会失败,这是在异步代码中的一种最干净的方式来处理错误。

咱们还可使用带有循环和条件的 async 函数:

async function count() {

let counter = 1
for (let i = 0; i < 100; i++) {
    counter += 1
    console.log(counter)
    await sleep(1000)
}

}
这是一个很简答的例子,若是运行这段程序,将会看到代码在 sleep 调用时暂停,下一个循环迭代将会在1秒后启动。

要点和细节

相信咱们已经感觉到了 asyns 和 await 的美妙之处,接下来让咱们深刻了解一下细节:

async 和 await 创建在 Promise 之上。使用 async,老是会返回一个 Promise。请记住这一点,由于这也是容易犯错的地方。
当执行到 await 时,程序会暂停当前函数,而不是全部代码
async 和 await 是非阻塞的
依旧可使用 Promise helpers,例如 Promise.all( )
正如以前的示例:

async function logPosts () {

try {
    let user_id = await fetch('/api/users/username')
    let post_ids = await fetch('/api/posts/<code>${user_id}')
    let promises = post_ids.map(post_id => {
        return  fetch('/api/posts/${post_id}')
    }
    let posts = await Promise.all(promises)
    console.log(posts)
} catch (error) {
    console.error('Error:', error)
}

}
await 只能用于声明为 async 的函数中
所以,不能在全局范围内使用 await
以下代码:

// throws an error
function logger (callBack) {

console.log(await callBack)

}

// works!
async function logger () {

console.log(await callBack)

}

现已正式可用

到2017年6月,几乎全部浏览器均可以使用 async 和 await。为了确保你的代码随时可用,则须要使用 Babel 将你的 JavaScript 代码编译为旧浏览器也支持的语法。

若是对更多ES2017内容感兴趣,请访问ES2017特性的完整列表。

JavaScript 开发工具推荐

SpreadJS 纯前端表格控件是基于 HTML5 的 Java 电子表格和网格功能控件,提供了完备的公式引擎、排序、过滤、输入控件、数据可视化、Excel 导入/导出等功能,适用于 .NET、Java 和移动端等各平台在线编辑类 Excel 功能的表格程序开发。

原文连接:https://css-tricks.com/using-...

转载请注明出自:葡萄城控件

相关文章
相关标签/搜索