ES6+--》熟知JS中的async函数

这篇具有很好参考价值的文章主要介绍了ES6+--》熟知JS中的async函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

async函数

await 表达式

async使用形式

async读取文件

async发送AJAX请求

与生成器(Generator)相比


async函数

async函数的返回值为 promise 对象,promise对象的结果由async函数执行的返回值决定。async函数能使得异步操作变得更加方便,简而言之就是 Generator 的语法糖。

定义async函数,特点是即便函数内部返回结果不是promise对象,调用函数其最后的返回结果依然是promise对象,代码如下:

如果返回的结果不是 Promise 对象的情况下:

<script>
    async function fn(){
        // 返回的结果是字符串
        // return '123'
        // // 返回的结果是undefined
        // return;
        // 返回的结果是抛出一个异常
        throw new 'error'
    }
    const result = fn()
    console.log(result);
</script>

箭头函数 async,# JavaScript,javascript,前端,es6,ecmascript,开发语言

如果返回的结果是 Promise 对象时,我们正常使用 then 方法即可,如下:

<script>
    async function fn(){
        return new Promise((resolve,reject)=>{
            // resolve('成功的数据')
            reject('失败的数据')
        })
    }
    const result = fn()
    // 调用 then 方法
    result.then((value)=>{
        console.log(value);
    },(reason)=>{
        console.log(reason); // 打印失败的数据
    })
</script>

await 表达式

通过上文的对 async 介绍,感觉其功能有点鸡肋,其实恰恰不是,而是 async 需要搭配 await 一起使用才能达到语法糖的效果。

await的特点

await必须写在 async 函数中

await右侧的表达式一般为 promise 对象

await返回的是 promise 成功的值

await的 promise 失败了,就会抛出异常,需要通过 try...catch捕获处理

说白了:await就相当于 then 方法的第一个回调函数,只返回成功的值,失败的值需要 try...catch来捕获。

async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。

<script>
    const p = new Promise((resolve,reject)=>{
        // resolve('用户数据')
        reject('用户加载数据失败了')
    })
    async function fn(){
        // 为防止promise是失败的状态,加上try...catch进行异常捕获
        try {
            // await 返回的结果就是 promise 返回成功的值
            let result = await p
            console.log(result);
        } catch (error) {
            console.log(error);//因为是失败的状态,所以打印:用户加载数据失败了
        }
    }
    fn()
</script>

总结

(1)await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。

(2)如果有多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。

比如:await Promise.all([a(), b()]),这里简单提一下

(3)await命令只能用在async函数之中,如果用在普通函数,就会报错。

(4)(理解一下async的运行原理) async 函数可以保留运行堆栈,普通函数内部运行一个异步任务时,如果异步任务运行结束普通函数可能早就运行完了,异步任务的上下文环境已经消失了,如果异步任务报错,错误堆栈将不包括普通函数;而async函数内部的异步任务运行时,async函数是暂停执行的,所以一旦async函数内部的异步任务运行报错,错误堆栈将包括async函数。

async使用形式

// 函数声明
async function foo() {}

// 函数表达式
const foo = async function () {};

// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)

// Class 的方法
class Storage {
  constructor() {
    this.cachePromise = caches.open('avatars');
  }

  async getAvatar(name) {
    const cache = await this.cachePromise;
    return cache.match(`/avatars/${name}.jpg`);
  }
}

const storage = new Storage();
storage.getAvatar('jake').then(…);

// 箭头函数
const foo = async () => {};

async读取文件

和之前讲解的 promise 读取文件内容 一样,我们也可以使用async进行文件的读取,代码如下:

// 1.引入 fs 模块
const fs = require('fs')

// 2.读取文件
function index(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./index.md',(err,data)=>{
            // 如果失败
            if(err) reject(err)
            // 如果成功
            resolve(data)
        })
    })
}
function index1(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./index1.md',(err,data)=>{
            // 如果失败
            if(err) reject(err)
            // 如果成功
            resolve(data)
        })
    })
}
function index2(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./index2.md',(err,data)=>{
            // 如果失败
            if(err) reject(err)
            // 如果成功
            resolve(data)
        })
    })
}

// 3.声明一个 async 函数
async function fn(){
    let i = await index()
    let i1 = await index1()
    let i2 = await index2()
    console.log(i.toString());
    console.log(i1.toString());
    console.log(i2.toString());
}
fn()

箭头函数 async,# JavaScript,javascript,前端,es6,ecmascript,开发语言

async发送AJAX请求

和之前讲解 promise发送ajax请求 一样,我们也可以使用async进行发送ajax请求,代码如下:

<script>
    // 发送 AJAX请求,返回的结果是 Promise 对象
    function sendAjax(url){
        return new Promise((resolve,reject)=>{
            // 创建对象
            const x = new XMLHttpRequest()

            // 初始化
            x.open('GET',url)

            // 发送
            x.send()

            // 事件绑定
            x.onreadystatechange = function(){
                if(x.readyState === 4){
                    if(x.status >= 200 && x.status < 300){
                        // 如果响应成功
                        resolve(x.response)
                        // 如果响应失败
                        reject(x.status)
                    }
                }
            }
        })
    }
        
    // promise then 方法测试
    // const result = sendAjax("https://ai.baidu.com/").then(value=>{
    //     console.log(value);
    // },reason=>{})
    // async 与 await 测试
    async function fn(){
        // 发送 AJAX 请求
        let result = await sendAjax("https://ai.baidu.com/")
        console.log(result);
    }
    fn()
</script>

箭头函数 async,# JavaScript,javascript,前端,es6,ecmascript,开发语言

与生成器(Generator)相比

我们发现 async与await之间的关系 和 Generator与yield之间的关系十分类似,不熟悉Generator的朋友可以看一下我之前的文章:生成器讲解 ;一比较就发现: async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await。代码比较如下:

<script>
    // Generator 函数
    function * person() {
        console.log('hello world');
        yield '第一分隔线' 
    
        console.log('hello world 1');
        yield '第二分隔线'
    
        console.log('hello world 2');
        yield '第三分隔线'
    }
    let iterator = person()
    // console.log(iterator); 打印的就是一个迭代器对象,里面有一个 next() 方法,我们借助next方法让它运行
    iterator.next()
    iterator.next()
    iterator.next()

    // async函数
    const person1 = async function (){
        console.log('hello world');
        await '第一分隔线' 
    
        console.log('hello world 1');
        await '第二分隔线'
    
        console.log('hello world 2');
        await '第三分隔线'
    }
    person1()
</script>

箭头函数 async,# JavaScript,javascript,前端,es6,ecmascript,开发语言

async函数的实现原理就是将 Generator 函数和自动执行器包装在一个函数里。

<script>
    async function fn(args) {}
    // 等同于
    function fn(args) {
        // spawn函数就是自动执行器
        return spawn(function* () {});
    }
</script>

我们可以分析一下 Generator 和 async 代码的书写特点和风格:

<script>
    // Generator 函数
    function Generator(a, b) {
        return spawn(function*() {
            let r = null;
            try {
                for(let k of b) {
                r = yield k(a);
                }
            } catch(e) {
                /* 忽略错误,继续执行 */
            }
            return r;
        });
    }

    // async 函数
    async function async(a, b) {
        let r = null;
        try {
            for(let k of b) {
            r = await k(a);
            }
        } catch(e) {
         /* 忽略错误,继续执行 */
        }
        return r;
    }
</script>

所以 async 函数的实现符合语义也很简洁,不用写Generator的自动执行器,改在语言底层提供,因此代码量少。 

从上文代码我们可以总结以下几点

(1)Generator函数执行需要借助执行器,而async函数自带执行器,即async不需要像生成器一样需要借助 next 方法才能执行,而是会自动执行。

(2)相比于生成器函数,我们可以看到 async 函数的语义更加清晰

(3)上面就说了,async函数可以接受Promise或者其他原始类型,而生成器函数yield命令后面只能是Promise对象或者Thunk函数。

(4)async函数返回值只能是Promise对象,而生成器函数返回值是 Iterator 对象文章来源地址https://www.toymoban.com/news/detail-799281.html

到了这里,关于ES6+--》熟知JS中的async函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ES6】 JavaScript 中的Object.assign

    Object.assign() 是 JavaScript 中的一个方法,它用于复制源对象的所有可枚举属性到目标对象。该方法会返回目标对象。 这是其基本用法: 在这个例子中,source 对象的所有可枚举属性都被复制到了 target 对象。 需要注意的是,Object.assign() 是浅复制(shallow copy),意味着如果源对

    2024年02月10日
    浏览(53)
  • 【ES6】JavaScript 中的数组方法reduce

    reduce() 是一个 JavaScript 中的数组方法,它会对数组的每个元素执行一个提供的 reducer 函数,将其减少到一个单一的值。 这是 reduce() 的基本用法: 这里: callback 是一个用于每个数组元素的函数,接受四个参数: accumulator:累加器累加回调的返回值。它是上一次调用回调时返回

    2024年02月10日
    浏览(33)
  • JavaScript全解析——ES6函数中参数的默认值和解构赋值

    本文为千锋资深前端教学老师带来的【JavaScript全解析】系列,文章内含丰富的代码案例及配图,从0到1讲解JavaScript相关知识点,致力于教会每一个人学会JS! 文末有本文重点总结,可以收藏慢慢看~ 更多技术类内容,主页关注一波! 给函数的形参设置一个默认值, 当你没有传

    2024年02月05日
    浏览(43)
  • 【JavaScript】探索ES6中的数组API:简洁高效的操作方式

    ES6 ( ECMAScript 2015 )是 JavaScript 语言的一个重要版本,为编写更加简洁、便捷和可读性更高的代码提供了很多新的特性和 API。想了解ES6所有新增API,可以跳转至我的另一篇博客:JS语法 ES6、ES7、ES8、ES9、ES10、ES11、ES12新特性 其中 数组相关的 API 也在 ES6 中得到了大大的增强,

    2024年02月09日
    浏览(50)
  • JavaScript Es6_2笔记 (深入对象 + 内置构造函数 + 包装类型)+包含实例方法

    了解面向对象编程的基础概念及构造函数的作用,体会 JavaScript 一切皆对象的语言特征,掌握常见的对象属性和方法的使用。 了解面向对象编程中的一般概念 能够基于构造函数创建对象 理解 JavaScript 中一切皆对象的语言特征 理解引用对象类型值存储的的

    2024年02月12日
    浏览(47)
  • 【ES6】箭头函数和普通函数的区别

    它们之间的区别: (1)箭头函数没有自己的this。 (2)不可以当作构造函数,不可以对箭头函数使用new命令,否则抛出错误。 (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。 (4)不可以使用yield命令,箭头函数不能用作 Generator

    2024年02月12日
    浏览(36)
  • 解析 angular subscribe中, ES6 Arrow 箭头函数

    箭头函数表达式 的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。 在hero.component中 我们定义了一个函数来获取hero.service的请求 getHeroes(): void {     this.heroService.getH

    2024年02月12日
    浏览(41)
  • ES6系列之let、const、箭头函数使用的坑

    变量提升 块级作用域的重要性 箭头函数this的指向 rest参数和arguments Babel是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码,从而在老版本的浏览器执行。这意味着,你可以用ES6的方式编写程序,又不用担心现有环境是否支持。  上面的原始代码用了箭头函数,Babel将其转

    2024年02月14日
    浏览(42)
  • 箭头函数 - JavaScript的新宠儿

    📢 鸿蒙专栏:想学鸿蒙的,冲 📢 C语言专栏:想学C语言的,冲 📢 VUE专栏:想学VUE的,冲这里 📢 CSS专栏:想学CSS的,冲这里 📢 Krpano专栏:想学VUE的,冲这里  📢 JavaScript专栏:想学JavaScript的,冲这里 🔔 上述专栏,都在不定期持续更新中!!!!!!! 目录 ✨ 前

    2024年01月17日
    浏览(46)
  • JavaScript高级 |如何玩转箭头函数?

    本文已收录于专栏 ⭐️ 《JavaScript》⭐️ 在ES6中新增了函数的简写方式----箭头函数,箭头函数的出现不仅简化了大量代码,也让代码看起来更加优雅,同时也解决了this指向问题,下面我们就来详细讲解如何玩转箭头函数。 之前的方法 箭头函数完整写法 箭头函数遍历数组

    2024年01月17日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包