Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重学js —— 函数:异步函数定义 #86

Open
lizhongzhen11 opened this issue Mar 12, 2020 · 0 comments
Open

重学js —— 函数:异步函数定义 #86

lizhongzhen11 opened this issue Mar 12, 2020 · 0 comments
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN

Comments

@lizhongzhen11
Copy link
Owner

lizhongzhen11 commented Mar 12, 2020

异步函数定义

// 来自 高级前端面试
function wait() {
  return new Promise(resolve => setTimeout(resolve, 10 * 1000))
}

async function main() {
  console.time();
  await wait();
  await wait();
  await wait();
  console.timeEnd();
}
main();
// 输出什么呢?
// 大概30s多一点

注意:当 Await 参数存在时,await 被解析为 AwaitExpressionAwait 参数出现在以下上下文中:

Module 是句法 goal symbol[Await] 参数存在,await 被解析为关键字并且会导致语法错误。当 Script 是句法 goal symbol,如果 [Await] 参数存在,await 可能会被解析为标识符。包含以下上下文:

BoundNames

AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }

  1. 返回 BindingIdentifier 的 BoundNames

AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }

  1. 返回 « "*default*" »

实例化函数对象

伴有参数 scope

AsyncFunctionDeclaration : async function BindingIdentifier ( 形参 ) { AsyncFunctionBody }

  1. 定义 nameBindingIdentifier 的字符串值
  2. 定义 F! OrdinaryFunctionCreate(%AsyncFunction.prototype%, 形参, AsyncFunctionBody, non-lexical-this, scope)
  3. 执行 ! SetFunctionName(F, name)
  4. F.[[SourceText]] 赋值为 AsyncFunctionDeclaration 匹配的 源文本
  5. 返回 F

AsyncFunctionDeclaration : async function ( 形参 ) { AsyncFunctionBody }

  1. 定义 F! OrdinaryFunctionCreate(%AsyncFunction.prototype%, 形参, AsyncFunctionBody, non-lexical-this, scope)
  2. 执行 ! SetFunctionName(F, "default")
  3. F.[[SourceText]] 赋值为 AsyncFunctionDeclaration 匹配的 源文本
  4. 返回 F

EvaluateBody

伴有参数 functionObjectList argumentsList

AsyncFunctionBody : FunctionBody

  1. 定义 promiseCapability! NewPromiseCapability(%Promise%)
  2. 定义 declResultFunctionDeclarationInstantiation(functionObject, argumentsList)
  3. 如果 declResult 不是 abrupt completion
    1. 执行 ! AsyncFunctionStart(promiseCapability, FunctionBody)
  4. 否则,
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « declResult.[[Value]] »)
  5. 返回 Completion { [[Type]]: return, [[Value]]: promiseCapability.[[Promise]], [[Target]]: empty }

求值

AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }

async function test(arg) {
  // ...
}
  1. 返回 NormalCompletion(empty)

AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }

  1. 返回 NormalCompletion(empty)

AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }

const test = async function(arg) {
  // ...
}
  1. 定义 scope运行时执行上下文LexicalEnvironment
  2. 定义 closure! OrdinaryFunctionCreate(%AsyncFunction.prototype%, 形参, AsyncFunctionBody, non-lexical-this, scope)
  3. closure.[[SourceText]] 赋值为 AsyncFunctionExpression 匹配的 源文本
  4. 返回 closure

AsyncFunctionExpression : async function BindingIdentifier( FormalParameters ) { AsyncFunctionBody }

const test = async function fn(arg) {
  // ...
}
  1. 定义 scope运行时执行上下文LexicalEnvironment
  2. 定义 funcEnv! NewDeclarativeEnvironment(scope)
  3. 定义 envRecfuncEnvEnvironmentRecord
  4. 定义 name绑定标识符 字符串值
  5. 执行 ! envRec.CreateImmutableBinding(name, false)
  6. 定义 closure! OrdinaryFunctionCreate(%AsyncFunction.prototype%, 形参, AsyncFunctionBody, non-lexical-this, funcEnv)
  7. 执行 ! SetFunctionName(closure, name)
  8. 执行 ! envRec.InitializeBinding(name, closure)
  9. closure.[[SourceText]] 赋值为 AsyncFunctionExpression 匹配的 源文本
  10. 返回 closure

AwaitExpression : await 一元表达式

await console.log('await')
  1. 定义 exprRef一元表达式 求值结果
  2. 定义 value? GetValue(exprRef)
  3. 返回 ? Await(value)

2020-03-18 补充

// 来自高级前端面试,我选错了
async function getData() {
  return await Promise.resolve('I made it!');
}

const data = getData();
console.log(data); // 选C

A. "I made it!"
B. Promise {<resolved>: "I made it!"}
C. Promise {<pending>}
D. undefined

// 如果再加上下面这段代码
setTimeout(() => console.log(data), 1000)
// 那么会输出我想要的答案:
Promise {<resolved>: "I made it!"}

// 不加 setTimeout 该如何修改呢?
const data = await getData();
console.log(data); // Promise {<resolved>: "I made it!"}

2020-07-18 补充

前两天在对接苏宁联盟淘客API时遇到了小问题,记录下。

我调了它的推荐商品api,期望能拿到商品下的优惠券信息,包括以领取情况,令人失望的是,这个接口没给出,需要我拿到券URL再去调 https://open.suning.com/ospos/apipage/toApiMethodDetailMenuNew.do?interCode=suning.netalliance.couponinfo.query 这个接口才能得到券领用情况。

这样我就不得不再商品列表接口返回时遍历再去调用接口,直接用下面代码返回的 list 是由空对象组成的数组,很明显不对:

// 省略...
const result = await this.httpService.post(snApiUrl +'/'+ snApiType.RECOMMEND, data, { headers: headersData }).toPromise();
const queryResult = JSON.parse(result.data['sn_responseContent']['sn_body']['querySelectrecommendcommodity']['commodityList']);
return { // 推荐列表返回统一格式
  current: +current,
  total: queryResult.totalCount,
  list: queryResult.data.map(async item => {
    const couponinfo = await this.httpService.post(snApiUrl +'/'+ snApiType.COUPONINFO_QUERY, queryData, { headers: headersData }).toPromise();
    if (couponinfo.data['sn_responseContent']['sn_error']) {
      continue;
    }
    const couponCount = couponinfo.data['sn_responseContent']['sn_body']['queryCouponinfo']['couponCount']; // 优惠券总数
    const couponRemainingAmount = couponinfo.data['sn_responseContent']['sn_body']['queryCouponinfo']['couponRemainingAmount']; // 优惠券剩余数量
    const coupon_received_percent = (((couponCount - couponRemainingAmount) / couponCount) * 100).toFixed() + '%';
    return {
      // 省略...
      coupon_received_percent: coupon_received_percent , // 优惠券已领取占比
    }
  }),
  pageSize: 10,
}

后来我用了 for await of 才将其解决!

这个问题本质是异步函数内调用接口等待返回数据后,再对返回数据进行遍历,遍历过程中还需要去调接口拿数据,即异步套异步,单纯在 map 里面加 async 并不能立即拿到数据

2020-07-25 补充

Daily-Interview-Question——第 160 题

@lizhongzhen11 lizhongzhen11 added js基础 Good for newcomers 重学js 重学js系列 规范+MDN labels Mar 12, 2020
This was referenced Mar 12, 2020
@lizhongzhen11 lizhongzhen11 changed the title 重学js —— 异步函数定义 重学js —— 函数:异步函数定义 Mar 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN
Projects
None yet
Development

No branches or pull requests

1 participant