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 —— 控制抽象对象之Promise #131

Open
lizhongzhen11 opened this issue Jul 16, 2020 · 0 comments
Open

重学js —— 控制抽象对象之Promise #131

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

Comments

@lizhongzhen11
Copy link
Owner

lizhongzhen11 commented Jul 16, 2020

控制抽象对象之Promise

Promise 是一个 用来当作延迟(可能是异步的)计算的最终结果的占位符 对象。

所有 Promise 对象都会处于 fulfilledrejectedpending 三个 互斥状态 中的一种。

  • promise对象 p,如果 p.then(f, r) 立即入队一个 任务 调用函数 f,则 pfulfilled 状态
  • promise对象 p,如果 p.then(f, r) 立即入队一个 任务 调用函数 r,则 prejected 状态
  • promise对象 p,如果它既不是 fulfilled 又不是 rejected,则处于 pending 状态

如果已解决 promise 或已将其“锁定”去匹配另一个 promise 的状态,则该 promiseresolved。尝试解决或拒绝一个已解决的 promise 没有任何影响。如果 promise 未解决,则其为 unresolved。未解决的 promise 处于 pending 状态。已解决的 promise 可能处于 pendingfulfilledrejected 状态。

Promise构造器

  • 即固有对象 %Promise%
  • 全局对象 "Promise" 属性的初始值
  • ...

Promise ( executor )

  1. 如果 NewTargetundefined,抛 TypeError 异常
  2. 如果 executor 不可调用,抛 TypeError 异常
  3. 定义 promise? OrdinaryCreateFromConstructor(NewTarget, "%Promise.prototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »)
  4. promise.[[PromiseState]] 设置为 pending
  5. promise.[[PromiseFulfillReactions]] 设置为空 List
  6. promise.[[PromiseRejectReactions]] 设置为空 List
  7. promise.[[PromiseIsHandled]] 设置为 false
  8. 定义 resolvingFunctionsCreateResolvingFunctions(promise)
  9. 定义 completionCall(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)
  10. 如果 completionabrupt completion
    1. 执行 ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »)
  11. 返回 promise

Promise构造器属性

Promise.all ( iterable )

  • MDN
  • 即固有对象 %Promise_all%
  1. 定义 Cthis
  2. 定义 promiseCapability? NewPromiseCapability(C) (PS:该方法用来创建Promise对象并提取 resolvereject 函数)
  3. 定义 promiseResolveGetPromiseResolve(C) (PS:拿 resolve 函数)
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability) (PS:设置 promiseResolve 值为 promiseResolve.[[Value]]
  5. 定义 iteratorRecordGetIterator(iterable)
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)
  7. 定义 resultPerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)
  8. 如果 resultabrupt completion
    1. 如果 iteratorRecord.[[Done]]false,将 result 设置为 IteratorClose(iteratorRecord, result)
    2. IfAbruptRejectPromise(result, promiseCapability)
  9. 返回 Completion(result)

核心在于 PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve) 。最后一个 Promise resolve 完才会调用 resultCapability.[[Resolve]]。最后返回的是 resultCapability.[[Promise]]

Promise.allSettled ( iterable )

  • MDN
  • Promise.all() 不同,Promise.all() 返回所有 Promise 执行后的 value,但是这个方法返回所有 Promise 执行后的 Promise 对象!!!
  1. 定义 Cthis
  2. 定义 promiseCapability? NewPromiseCapability(C) (PS:该方法用来创建Promise对象并提取 resolvereject 函数)
  3. 定义 promiseResolveGetPromiseResolve(C) (PS:拿 resolve 函数)
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability) (PS:设置 promiseResolve 值为 promiseResolve.[[Value]]
  5. 定义 iteratorRecordGetIterator(iterable)
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)
  7. 定义 resultPerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve)
  8. 如果 resultabrupt completion
    1. 如果 iteratorRecord.[[Done]]false,将 result 设置为 IteratorClose(iteratorRecord, result)
    2. IfAbruptRejectPromise(result, promiseCapability)
  9. 返回 Completion(result)

Promise.race ( iterable )

  1. 定义 Cthis
  2. 定义 promiseCapability? NewPromiseCapability(C) (PS:该方法用来创建Promise对象并提取 resolvereject 函数)
  3. 定义 promiseResolveGetPromiseResolve(C) (PS:拿 resolve 函数)
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability) (PS:设置 promiseResolve 值为 promiseResolve.[[Value]]
  5. 定义 iteratorRecordGetIterator(iterable)
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability)
  7. 定义 resultPerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve)
  8. 如果 resultabrupt completion
    1. 如果 iteratorRecord.[[Done]]false,将 result 设置为 IteratorClose(iteratorRecord, result)
    2. IfAbruptRejectPromise(result, promiseCapability)
  9. 返回 Completion(result)

Promise.reject ( r )

  • MDN
  • 即固有对象 %Promise_reject%
  1. 定义 Cthis
  2. 定义 promiseCapability? NewPromiseCapability(C) (PS:该方法用来创建Promise对象并提取 resolvereject 函数)
  3. 执行 ? Call(promiseCapability.[[Reject]], undefined, « r »)
  4. 返回 promiseCapability.[[Promise]]

Promise.resolve ( x )

  • MDN
  • 即固有对象 %Promise_resolve%
  1. 定义 Cthis
  2. 如果 C 不是对象,抛 TypeError 异常
  3. 返回 ? PromiseResolve(C, x)

Promise.any()

看MDN,了解下

Promise原型对象上的属性

  • 即固有对象 %PromisePrototype%
  • [[Prototype]] 内置插槽其值为 %Object.prototype%
  • 属于 普通对象
  • 没有 [[PromiseState]] 内置插槽以及任何其它属于 Promise 实例的内置插槽

Promise.prototype.catch ( onRejected )

  1. 定义 promisethis
  2. 返回 ? Invoke(promise, "then", « undefined, onRejected »)

Promise.prototype.finally ( onFinally )

  1. 定义 promisethis
  2. 如果 promise 不是对象,抛 TypeError 异常
  3. 定义 C? SpeciesConstructor(promise, %Promise%)
  4. 断言:C 是构造器
  5. 如果 onFinally 不可调用,
    1. 定义 thenFinallyonFinally
    2. 定义 catchFinallyonFinally
  6. 否则,
    1. 定义 stepsThenFinallyThen Finally Functions 中定义的算法步骤
    2. 定义 thenFinally! CreateBuiltinFunction(stepsThenFinally, « [[Constructor]], [[OnFinally]] »)
    3. thenFinally.[[Constructor]] 设置为 C
    4. thenFinally.[[OnFinally]] 设置为 onFinally
    5. 定义 stepsCatchFinallyCatch Finally Functions 中定义的算法步骤
    6. 定义 catchFinally! CreateBuiltinFunction(stepsCatchFinally, « [[Constructor]], [[OnFinally]] »)
    7. catchFinally.[[Constructor]] 设置为 C
    8. catchFinally.[[OnFinally]] 设置为 onFinally
  7. 返回 ? Invoke(promise, "then", « thenFinally, catchFinally »)

Promise.prototype.then ( onFulfilled, onRejected )

  • MDN
  • 即固有对象 %PromiseProto_then%
  1. 定义 promisethis
  2. 如果 promise 不是 Promise,抛 TypeError 异常
  3. 定义 C? SpeciesConstructor(promise, %Promise%)
  4. 定义 resultCapability? NewPromiseCapability(C)
  5. 返回 PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)

Promise实例上的属性

内置插槽 描述
[[PromiseState]] pendingfulfilledrejected 其中之一。控制promise如何响应对即将到来的 then 方法调用。
[[PromiseResult]] 已完成或已拒绝的promise的值。表明 [[PromiseState]] 不是 pending
[[PromiseFulfillReactions]] 一个 PromiseReaction 记录 List,当promise从 pending 状态转换为 fulfilled 状态时将被处理。
[[PromiseRejectReactions]] 一个 PromiseReaction 记录 List,当promise从 pending 状态转换为 rejected 状态时将被处理。
[[PromiseIsHandled]] boolean 值,表示promise是否已有完成或拒绝处理程序;用于未处理的拒绝跟踪

思考

异步

new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000)).then(res => console.log(res))
// 谷歌浏览器(83.0.4103.116(正式版本))立即打印 
Promise {
  [[PromiseStatus]]: 'pending',
  [[PromiseValue]]: undefined
}
// 约3s左右打印 
3
// 此时 Promise 对象变为
Promise {
  [[PromiseStatus]]: 'resolved',
  [[PromiseValue]]: undefined
}

以上述代码为例,Promise 到底是如何等待异步任务完成的?如何监听到异步任务完成?

难不成浏览器底层一直在循环等待???等到异步执行完成返回结果???

其实这里就涉及到另一个知识点:事件循环。
根据 winter《重学前端》介绍,在底层的 C/C++ 代码中,这个事件循环是一个跑在独立线程中的循环,用伪代码来表示,大概是这样的:

while(TRUE) {
  r = wait();
  execute(r);
}

我们可以看到,整个循环做的事情基本上就是反复“等待 - 执行”。当然,实际的代码中并没有这么简单,还有要判断循环是否结束、宏观任务队列等逻辑,这里为了方便你理解,我就把这些都省略掉了。——抄自winter《重学前端》 Promise里的代码为什么比setTimeout先执行? 一章。

拓展阅读

2020-07-29 补充

来自高级前端面试小程序

function wait() {
  return new Promise(resolve => setTimeout(resolve, 10 * 1000))
}

async function main() {
  console.time();
  const x = wait();
  const y = wait();
  const z = wait();
  await x;
  await y;
  await z;
  console.timeEnd();
}
main();

稍微有点迷惑人,但其实这三个 Promise 是差不多同时执行的,最终返回结果也就比 10000 多点吧。

改成下面:

function wait() {
  return new Promise(resolve => setTimeout(resolve, 10 * 1000))
}

async function main() {
  console.time();
  const x = await wait();
  const y = await wait();
  const z = await wait();
  console.timeEnd();
}
main();

修改后的代码最终结果应该比 30000 多点

@lizhongzhen11 lizhongzhen11 added js基础 Good for newcomers 重学js 重学js系列 规范+MDN labels Jul 16, 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