完全理解async/await

2022-12-19 0 257

具体来说他们晓得generator表达式是两个计算机程序,它会回到两个插值器第一类,那个第一类有两个next方式,透过初始化next方式就能从外部赢得generator的继续执行控股权,

他们也能透过value领到继续执行后的结论,因此generator也能用以处置触发器。

比如:

function* fetchGenerator() { const url = https://baidu.com; const res = yield fetch(url); return res; }

他们在初始化gen表达式去赢得回到结论的这时候,就如需那么做:

const gen = fetchGenerator(); const result = gen.next(); result.value.then(data => data.json()).then(data => gen.next(data));

这里fetch回到的是两个promise,因此result.value就是两个pr然后再将data传递给gen.next(),这样就能将data赋值给yield左边的res,这样就能领到fetch的请求结论了。

然后这只

function* fetchGenerator(){ const res1 = yield fetch(https://baidu.com); const res2 = yield fetch(https://google.com); const res3 = yield fetch(https://bing.com); return [res1, res2, res3]; } const gen = fetchGenerator(), result = gen.next(); result.value .then(data => data.json()) .then(data => gen.next(data).value) .then(data => data.json()) .then(data => gen.next(data).value) .then(data => data.json()) .then(data => gen.next(data).value)

那么有没有一种方式,能不需要他们自己手动初始化next,而是让generator自动继续执行呢?他们能利用while循环来做,只要gen.next().done不为true,就一直循环继续执行:

let g = gen(); let res = g.next(); while(!res.done) { // todo something res = g.next() }

上面的代码会一下子继续执行完毕,但如果有的请求需要上两个请求结束后再发送下两个请求,上面的代码是无法保证顺序的。

那么他们能利用promise的then来保证前一步继续执行完,再继续执行后一步,具体实现如下:

function run(gen) { const g = gen(); function next(data) { const result = g.next(data); if (result.done) { return result.value; } result.value .then(data => data.json()) .then(data => next(data)); } next(); } run(fetchGenerator);

其实著名的co模块也是为了解决那个问题出现的,以上就是co模块的简化实现了。

async

async function foo(){ const res1 = await fetch(https://baidu.com); const res2 = await fetch(https://google.com); const res3 = await fetch(https://bing.com); } foo();

他们能看到async表达式的结构和generator表达式很相似,用async关键字代替了星号,await关键字代替了yield,且不需要他们再一步一步的去初始化next方式了,同时async回到的是两个Promise, 而不是iterator。都说async表达式是generator表达式的语法 ,那么那个语法糖到底是如何实现的呢?

他们来看下到底是如何实现的:

// async表达式回到的是两个// await后面回到的也是两个promise,能在后面直接跟then或者catch // async能看作是generator和co模块的组合,实现了generator表达式的自继续执行 function myAsync(gemeratorFc) { return function() { return new Promise((resolve, reject) => { const gen = gemeratorFc.apply(this, arguments); function next(key, val) { try { let res = gen[key](val); const { value, done } = res; if (done) { return resolve(value); // 这里的return是为了退出递归 } else { return Promise.resolve(value).then( // value有可能是个基础类型的值 // Promise.resolve接收的参数如果是个基础类型的值,则包一下转变为两个promise // 如果是两个promise,则直接回到那个promise val => next(next, val), err => next(throw, err) ) } } catch(e) { return reject(e);// 这里的return是为了退出递归 } } next(next); }) } }

async表达式的优点:

1.异常捕获更加优秀,由于promise触发器错误无法透过try…catch来捕获,因此他们一般会用try…catch来捕获Promise构造表达式中的错误,实际上非常繁琐的。

function test() { try { new Promise((resolve) => { // … }).then(() => { }).catch(() => { }) } catch (err) { console.log(err) } }

而在async里面,捕获错误很简单,只需要try…catch就能捕获所有异常。

async function test() { try { const res = await fetch(百度一下,你就晓得); } catch (err) { console.log(err) } }

除此之外,他们还能让 await 后面的 Promise 直接初始化 catch,这样能避免 `try…catch 处置多个不同错误时导致的问题。

async function test() { const res = await fetch(百度一下,你就晓得) .catch(err => { console.log(err) }) }

2.断点调试

由于 Promise then 的触发器缘故,导致打断点的这时候,经常会先走后面的代码,再回到 then 里面(先继续执行宏任务,再继续执行所有微任务),这样对于断点调试来说非常不方便。

但是在 async 里面,断点调试表现就像同步一样,让调试更加方便。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务