defineProperty中无法获取await get()的值
再来看看async/await
群里聊天时看到抛出的一个问题和相关代码,Object.defineProperty
中的get使用await为啥不能同步获取到值
用这俩语法糖执行同步任务也有一段时间了,看到这个问题还是有点懵,经过实践解决了这个问题
那通过MDN
重新再了解一下async/await
异步转同步的发展过程
- ajax需要在callback中获取结果,当有请求结果和请求参数有相互依赖时需要多层嵌套,出现回调地狱的代码问题
- 而Promise可以在then()中拿到结果,让每步调用写法更清晰,解决回调地狱
- async更简洁,更优雅的错误处理,易于调试
async
定义一个返回Promise对象的异步函数
await
会暂停异步函数的执行,并等待Promise执行,然后继续执行异步函数,并返回结果
是generator生成器的语法糖
通过俩例子了解一下async/await
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function getData(val) { let result = new Promise(res => { setTimeout(() => { console.log('异步结果', val) res(val) }, 500) }) console.log('异步getData', result) return result; } async function getVal(val) { let result = await getData(val) console.log('正常的异步转同步', result) return result; } console.log('getVal', getVal(1))
|
会发现打印的是一个Promise对象 pending状态,这也符合async的返回,而内部的函数是正常同步执行的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| async function getData2(val) { let result = await new Promise(res => { setTimeout(() => { console.log('异步2结果', val) res(val) }, 500) }) console.log('异步2getData2', result) return result; } async function getVal2(val) { let result = await getData2(val) console.log('依旧正常的异步转同步', result) } getVal2(33) console.log('这行还是会先于getVal2执行的哦')
|
原来,async/await 保证的是,同一个作用域中存在同步代码和异步代码时,等待获取到promise结果后再执行后续代码
如何解决get中的await取值
定义一个函数,改变对象的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function def(target, key, val) { Object.defineProperty(target, key, { async get() { let res = await new Promise(res => { setTimeout(() => { res('success') }, 2000) }) return val; }, set(newVal) { console.log('设置新的值', newVal) val = newVal } }) }
var a = { id: 1 } def(a, 'id', 1); a.id = 2; console.log('a.id---', a.id)
|
通过上文关于async/await的语法含义,解决这个问题就很简单了
目的是获取get中的await返回val而不是promise
通过代理包装一层async/await,就能正常获取get()的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| async function myProxy(val) { return await val; }
async function myProxyAddition(obj, key, num) { let result = await myProxy(obj[key]) let new_result = result + num; obj[key] = new_result; return new_result; }
async function myProxySubtraction(obj, key, num) { let result = await myProxy(obj[key]) let new_result = result - num; obj[key] = new_result; return new_result; } myProxyAddition(a, 'id', 3);
var timer = setInterval(async () => { let result = await myProxy(a.id) if (result >= 5) { clearInterval(timer) return; } myProxyAddition(a, 'id', 1); }, 1000)
[1, 1, 1, 1, 1].map(async () => { myProxyAddition(a, 'id', 1); })
|
虽然实际开发中不会遇到defineProperty中await get()的情况,但是通过这次的例子可以加深对语法糖的理解~