0
点赞
收藏
分享

微信扫一扫

servicecomb bmi例子无法正常启动

自由的美人鱼 04-16 18:30 阅读 3

上一节说,JavaScript异步操作需要通过Promise实现,一个Promise对象在操作网络时是异步的,等到返回后再调用回调函数,执行正确就调用then(),执行错误就调用catch()

虽然异步实现了,不会让用户感觉到页面“卡住”了,但是一堆then()catch()写起来麻烦看起来也乱。

有没有更简单的写法?

一、async函数

可以用关键字async配合await调用Promise,实现异步操作,但代码却和同步写法类似:

async function get(url) {
    let resp = await fetch(url);
    return resp.json();
}

使用async function可以定义一个异步函数,异步函数和Promise可以看作是等价的

在async function内部,用await调用另一个异步函数,写起来和同步代码没啥区别,但执行起来是异步的。

也就是说:

let resp = await fetch(url);

自动实现了异步调用,它和下面的Promise代码等价:

let promise = fetch(url);
promise.then((resp) => {
    // 拿到resp
})

如果我们要实现catch()怎么办?用Promise的写法如下:

let promise = fetch(url);
promise.then((resp) => {
    // 拿到resp
}).catch(e => {
    // 出错了
});

await调用时,直接用传统的try{ ... } catch

async function get(url) {
    try {
        let resp = await fetch(url);
        return resp.json();
    } catch (e) {
        // 出错了
    }
}

用async定义异步函数,用await调用异步函数,写起来和同步代码差不多,但可读性大大提高。

需要特别注意的是,await调用必须在async function中,不能在传统的同步代码中调用。

那么问题来了,一个同步function怎么调用async function呢?

首先,普通function直接用await调用异步函数将报错:

async function get(url) {
    let resp = await fetch(url);
    return resp.json();
}

function doGet() {
    let data = await get('/api/categories');
    console.log(data);
}

doGet();

如果把await去掉,调用实际上发生了,但我们拿不到结果,因为我们拿到的并不是异步结果,而是一个Promise对象:

async function get(url) {
    let resp = await fetch(url);
    return resp.json();
}

function doGet() {
    let promise = get('/api/categories');
    console.log(promise);
}

doGet();// [object Promise]

因此,在普通function中调用async function,不能使用await,但可以直接调用async function拿到Promise对象,后面加上then()catch()就可以拿到结果或错误了:

async function get(url) {
    let resp = await fetch(url);
    return resp.json();
}

function doGet() {
    let promise = get('/api/categories');
    promise.then(data => {
        // 拿到data
        document.getElementById('test-response-text').value = JSON.stringify(data);
    });
}

doGet();

因此,定义异步任务时,使用async function比Promise简单,调用异步任务时,使用await比Promise简单,捕获错误时,按传统的try...catch写法,也比Promise简单。只要浏览器支持,完全可以用async简洁地实现异步操作。

值得注意的是,虽然await使异步代码看起来像同步代码一样简单,但它并没有改变JavaScript的单线程和非阻塞特性。

await一个Promise时,JavaScript引擎会暂停当前async函数的执行,直到Promise解决或拒绝,然后继续执行后续的代码。在这个过程中,JavaScript引擎可以处理其他任务,比如事件监听、其他Promise的解决等,因此它仍然是非阻塞的。

举报

相关推荐

0 条评论