ES6 async

一、async

async的意思是"异步",顾名思义是有关异步操作有关的关键字。

例1:构造一个async方法

async function helloAsync(){
    return "helloAsync";
}
console.log(helloAsync());  //Promise {<resolved>: "helloAsync"}
  • 申明async方法只需在普通的函数前加上"async"关键字即可。
  • 执行这个函数,发现并没有返回字符串"helloAsync",而是通过Promise.resolved()将字符串封装成了一个Promise对象返回。

例2:返回的Promise对象,即用then方法来处理

async function helloAsync(){
    return "helloAsync";
}
helloAsync().then(function(v){
    console.log(v);  //"helloAsync"
})

二、await关键字

  • await关键字不能单独使用,是需要使用在async方法中
  • await的作用:阻塞主函数的执行,直到后面的Promise函数返回结果

例3:await后为Promise对象

function testAwait(){
    return new Promise(function(resolve){
        setTimeout(function(){
            console.log("testAwait");
            resolve();
        }, 1000);
    })
}
async function helloAsync(){
    await testAwait();
    console.log("helloAsync");
}
helloAsync();

分析代码:

  1. testAwait()方法中new一个Promise对象返回,Promise对象中用setTimeout模拟一个异步过程,即1s后打印"testAwait"。

  2. helloAsync()方法中,await testAwait(),表示将阻塞这里,等待testAwait这个异步方法执行并返回结果后,才继续下面的代码。

执行代码,1s后打印了如下结果:
在这里插入图片描述

  • await后面可以是Promise对象,也可以是字符串,布尔值,数值以及普通函数。

例4:await后为非Promise对象

function testAwait(){
    setTimeout(function(){
        console.log("testAwait");
    }, 1000);
}
async function helloAsync(){
    await testAwait();
    console.log("helloAsync");
}
helloAsync();

执行结果:
在这里插入图片描述
方法没有报错,说明await后面是支持非Promise函数的,但是执行的结果是不一样的,所以await针对所跟的表达式不同,有两种处理方式:

  1. 对于Promise对象,await会阻塞主函数的执行,等待 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果,然后继续执行主函数接下来的代码。

  2. 对于非Promise对象,await等待函数或直接量的返回,而不是等待其执行结果。

例5:将Promise对象变为rejected的处理

function testAwait(){
    return Promise.reject("error");
}
async function helloAsync(){
    await testAwait();
    console.log("helloAsync");  //没有打印
}
helloAsync().then(function(v){
    console.log(v);
 }).catch(function(e){
    console.log(e);  //"error"
});

在这里插入图片描述

  • 从执行结果看,返回reject状态被外层的catch捕获到,然后终止了后面的执行

例6:在有些情况下,出错后是希望继续执行,而不是中断。这种情况可以采用try…catch在函数内部捕获异常

function testAwait(){
    return Promise.reject("error");
}
async function helloAsync(){
    try{
        await testAwait();
    }
    catch(e){
        console.log("this error:"+e);  //this error:error
    }
    console.log("helloAsync");  //helloAsync
}
helloAsync().then(function(v){
    console.log(v);  //undefined
}).catch(function(e){
    console.log(e);
});

在这里插入图片描述

  • 异常被try…catch捕获后,继续执行下面的代码,没有导致中断

三、应用场景

await可以阻塞主函数,直到后面的Promise对象执行完成。这个特性就能很轻松的解决按顺序控制异步操作,即异步流程的问题。

在Generator中肚包鸡的制作过程的实例,现在用async/await来重写这个例子:

//准备
function prepare(){
    return new Promise((resolve) => {
           setTimeout(function(){
                 console.log("prepare chicken");
                 resolve();
           },500)
    });
}
//炒鸡
function fired(){
    return new Promise((resolve) => {
           setTimeout(function(){
                 console.log("fired chicken");
                 resolve();
           },500)
    });
}
//炖鸡
function stewed(){
    return new Promise((resolve) => {
           setTimeout(function(){
                 console.log("stewed chicken");
                 resolve();
           },500)
    });
}
//上料
function sdd(){
    return new Promise((resolve) => {
           setTimeout(function(){
                 console.log("sdd chicken");
                 resolve();
           },500)
    });
}
//上菜
function serve(){
    return new Promise((resolve) => {
           setTimeout(function(){
                 console.log("serve chicken");
                 resolve();
           },500)
    });
}
async function task(){
    console.log("start task");
    await prepare();
    await fired();
    await stewed();
    await sdd();
    await serve();
    console.log("end task");
}
task();

在这里插入图片描述
分析代码:

  • 首先每个制作异步过程封装成Promise对象。

  • 利用await阻塞原理,实现每个制作的顺序执行。

相比较Generator实现,无需run流程函数,实现了异步流程。

### ES6 中 `async` 和 `await` 的工作原理 #### 背景介绍 JavaScript 是一种单线程编程语言,这意味着它在同一时间只能执行一项操作。为了处理异步任务而不阻塞主线程,JavaScript 使用事件循环机制来管理回调函数队列。然而,在传统的基于回调或 Promise 的方式中编写异步代码可能会导致嵌套过深(即所谓的“回调地狱”)。为了解决这一问题,ES2017 引入了 `async/await` 关键字作为更简洁和易读的方式来处理异步逻辑。 --- #### 工作原理详解 ##### 1. **`async` 函数** 当一个函数被声明为 `async` 时,该函数会返回一个隐式的 `Promise` 对象[^1]。如果函数内部有显式的 `return` 返回值,则这个值会被自动封装成一个已解决状态的 `Promise`;如果有抛出错误的情况,则会变成拒绝状态的 `Promise`。 ```javascript async function exampleAsync() { return "Hello, world!"; } exampleAsync().then(value => console.log(value)); // 输出: Hello, world! ``` ##### 2. **`await` 表达式** `await` 只能在 `async` 函数内部使用,用于暂停当前函数的执行直到指定的 `Promise` 完成解析并返回其结果[^2]。在此期间,其他非同步的任务可以继续运行而不会受到影响。 - 如果等待的是一个已经完成的 `Promise` 或者是一个普通的值而非真正的 `Promise` 实例,那么 `await` 将立即恢复控制权并将相应数据传递给后续语句。 - 若目标 `Promise` 失败 (`reject`) ,则整个流程也会停止并向上传播异常除非被捕获。 ```javascript // 成功案例 async function fetchUserDataSuccess() { const user = await getUserData(); // 假设这是一个返回 Promise 的 API 请求方法 console.log(user); } // 错误捕获 async function fetchUserDataErrorHandling() { try { const user = await getInvalidUserData(); console.log(user); } catch (error) { console.error('Failed to load data:', error.message); } } ``` ##### 3. **底层实现细节** 实际上,`async/await` 并未改变 JavaScript 执行模型的核心——它们只是语法糖形式简化了对 Promises 的调用过程。每当遇到带有 `await` 的表达式时,编译器会在后台创建一个新的闭包环境保存上下文信息以便稍后再从中断处重新启动程序流[^3]。 --- #### 总结 通过引入 `async/await` 结构,开发者能够写出看起来像顺序执行但实际上却能高效利用资源的异步代码结构。这种方式不仅提高了可维护性和调试便利度,还减少了因复杂嵌套带来的潜在风险。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值