理解用 async/await 来处理异步

理解用 async/await 来处理异步

async的用法

async 作为一个关键字放到函数前面,用于表示函数是一个异步函数,因为 async 就是异步的意思, 异步函数也就意味着该函数的执行不会阻塞后面代码的执行。 写一个 async 函数。

async function func() {
  return 'hello world';
}

语法很简单,就是在函数前面加上 async 关键字,来表示它是异步的,那怎么调用呢?async 函数也是函数,平时我们怎么使用函数就怎么使用它,直接加括号调用就可以了,为了表示它没有阻塞它后面代码的执行,我们在 async 函数调用之后加一句 console.log;

async function func() {
    return 'hello world'
}
func();     // 直接调用 func() ,控制台没有返回
console.log( '虽然在后面,但是我先执行...' );

控制输出:

// 输出
虽然在后面,但是我先执行...

async 函数 func 调用了,但是没有任何输出,它不是应该返回 hello world,先不要着急,看一看 func() 执行返回了什么? 把上面的 func() 语句改为 console.log(func())

async function func() {
    return 'hello world'
}
console.log( func() );     //
console.log( '虽然在后面,但是我先执行...' );

控制输出:

Promise {<resolved>: "hello world"}     // console.log( func() );
虽然在后面,但是我先执行...                 // console.log( '虽然在后面,但是我先执行...' );

原来 async 函数返回的是一个 promise 对象,如果要获取到 promise 返回值,我们应该用 then 方法, 继续修改代码:

async function func() {
    return 'hello world';
}
func().then(result => {
    console.log(result);                // 后输出
});
console.log('虽然在后面,但是我先执行');    // 先输出

控制台输出:

虽然在后面,但是我先执行
hello world

获取到了 hello world, 同时 func 的执行也没有阻塞后面代码的执行。

这时,你可能注意到控制台中的 Promise 有一个 resolved,这是 async 函数内部的实现原理。如果 async 函数中有返回一个值,当调用该函数时,内部会调用 Promise. resolve() 方法把它转化成一个 promise 对象作为返回,但如果 func 函数内部抛出错误呢?那么就会调用 Promise.reject() 返回一个 promise 对象, 这时修改一下 func 函数。

async function func( flag ) {
    if( flag ) {
        return 'hello world'
    } else {
        throw 'my god, failure'
    }
}
console.log(func(true))  // 调用 Promise.resolve() 返回 promise 对象。
console.log(func(false)); // 调用 Promise.reject() 返回 promise 对象。

控制台输出:

Promise {<resolved>: "hello world"}
Promise {<rejected>: "my god, failure"}

如果函数内部抛出错误, promise 对象有一个catch 方法进行捕获。

func(false).catch(err => {
    console.log( err );
});

await的用法

await 是等待的意思,那么它等待什么呢,它后面跟着什么呢?其实它后面可以放任何表达式,不过我们更多的是放一个返回 promise 对象的表达式。注意 await 关键字只能放到 async 函数里面。

看例子:现在写一个函数,让它返回 promise 对象,该函数的作用是 2s 之后让数值乘以2

// 2s 之后返回双倍的值
function doubleAfter2seconds(num) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2 * num)
        }, 2000);
    } )
}

现在再写一个 async 函数,从而可以使用 await 关键字, await 后面放置的就是返回 promise 对象的一个表达式,所以它后面可以写上 doubleAfter2seconds 函数的调用

async function testResult() {
    let result = await doubleAfter2seconds(30);
    console.log(result);
}

控制台输出:

testResult();

// 输出
2s 之后,输出了 60

现在我们看看代码的执行过程,调用 testResult 函数,它里面遇到了awaitawait 表示等一下,代码就暂停到这里,不再向下执行了,它等什么呢?等后面的 promise 对象执行完毕,然后拿到 promise resolve 的值并进行返回,返回值拿到之后,它继续向下执行。具体到 我们的代码, 遇到 await 之后,代码就暂停执行了, 等待 doubleAfter2seconds(30) 执行完毕,doubleAfter2seconds(30) 返回的 promise 开始执行,2秒之后,promise resolve 了, 并返回了值为60, 这时 await 才拿到返回值60, 然后赋值给 result, 暂停结束,代码才开始继续执行,执行 console.log 语句。

就这一个函数,我们可能看不出 async/await 的作用,如果我们要计算3个数的值,然后把得到的值进行输出呢?

async function testResult() {
    let first = await doubleAfter2seconds(30);
    let second = await doubleAfter2seconds(50);
    let third = await doubleAfter2seconds(30);
    console.log( first + second + third );
}

6秒后,控制台输出220,我们可以看到,写异步代码就像写同步代码一样了,再也没有回调地域了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 异步编程对JavaScript语言太重要。Javascript语言的执行环境是“单线程”的,如果没有异步编程,根本...
    呼呼哥阅读 7,301评论 5 22
  • async 函数 含义 ES2017 标准引入了 async 函数,使得异步操作变得更加方便。 async 函数是...
    huilegezai阅读 1,257评论 0 6
  • 首先明确一个问题,为什么 Node.js 需要异步编程? JavaScript 是单线程的,在发出一个调用时,在没...
    Leondt阅读 614评论 1 3
  • 转载自边城https://segmentfault.com/a/1190000007535316 async 和 ...
    8d2855a6c5d0阅读 1,120评论 0 14
  • 1,耐心~如果,给所有品德排序的话,我一定将耐心排在第一~所以,我愿意停下来,看你流连在一只蝴蝶落在花瓣上,不催促...
    小菜姑娘阅读 371评论 0 0