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 #4

Open
BlackGanglion opened this issue Mar 19, 2017 · 6 comments
Open

[JS基础] Promise #4

BlackGanglion opened this issue Mar 19, 2017 · 6 comments

Comments

@BlackGanglion
Copy link
Owner

BlackGanglion commented Mar 19, 2017

参考:
你不知道的JavaScript(中卷)- Promise 部分
We have a problem with promises

@BlackGanglion BlackGanglion changed the title [JS基础] Promise知识点 [JS基础] Promise Mar 19, 2017
@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 3, 2017

由于 JavaScript 的单线程特性,函数执行具有原子性,称为完整运行(run-to-completion)特性

任务队列 (job queue),挂在事件循环队列的每个 tick 之后的一个队列。在事件循环的每个 tick 中,可能出现的异步动作不会导致一个完整的新事件添加到事件循环队列中,而会在当前 tick 的任务队列末尾添加一个项目(一个任务)。
任务处理是在当前事件循环 tick 结尾处,且定时器触发是为了调度下一个事件循环 tick。Promise 的异步特性是基于任务的。

Excuse me?这个前端面试在搞事!
Promise then中回调为什么是异步执行?

let a = 0;
Promise.resolve().then(() => {
  console.log(`Promise: ${a}`);
  return 2;
}).then((v) => {
  console.log(`Promise: ${v}`);
});
a++;
setTimeout(() => {
  a++;
  console.log(`setTime: ${a}`);
}, 0);
/*
Promise: 1
Promise: 2
setTime: 2
*/

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 3, 2017

回调函数存在的问题:
• 调用回调过早 (在追踪之前)
• 调用回调过晚 (或没有调用)
• 调用回调的次数太少或太多
• 没有把所需的环境 / 参数成功传给你的回调函数 (对参数需要做校验)
• 吞掉可能出现的错误或异常

Promise 是如何解决的?

  • .then 永远是异步调用,不会出现同步异步混用,导致竞态条件
  • .then 总是在当前事件循环 tick 结尾处,下个事件前
  • resolve 与 reject 必然会被调用一个,若本身不被决议,提供有竞态的高级抽象机制
  • resolve 与 reject 接受的参数只能一个,传递多值需要封装
  • Promise 可捕获错误
// 不会出现同步异步混用,导致竞态条件
getUserByName('nolan').then(function (user) {
  if (inMemoryCache[user.id]) {
    return inMemoryCache[user.id];    // returning a synchronous value!
  }
  return getUserAccountById(user.id); // returning a promise!
}).then(function (userAccount) {
  // I got a user account!
});

信任问题:
回调需要交给第三方来调用,调用次数等等无法很好控制。
Promise.resolve(..) 可以接受任何 thenable,将其解封为它的非 thenable 值。从 Promise. resolve(..) 得到的是一个真正的 Promise,是一个可以信任的值。
Promise.resolve(..) 会将传入的真正 Promise 直接返回,对传 入的 thenable 则会展开。

Promise.resolve(value);
Promise.resolve(promise);
Promise.resolve(thenable);

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 3, 2017

Promise 的异常处理
如果是 Promise 本身出错,那么会得到拒绝的 Promise。如果在 fulfilled/rejected 中则会立即抛出异常。

  • 使用 catch 统一处理,避免一级一级 reject,同时 catch 可以捕获 fulfilled 里抛出的异常
  • 全局监听 unhandledrejection 事件

参考:
Callback Promise Generator Async-Await 和异常处理的演进

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 5, 2017

macrotask和microtask
理解事件循环一(浅析)
理解事件循环二(macrotask和microtask)

microtasks:

  • process.nextTick
  • promise
  • Object.observe

macrotasks:

  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI 渲染

macrotasks 具有先后顺序,每个 macrotasks 执行完成后会将当前 microtasks 都执行完

image

@BlackGanglion
Copy link
Owner Author

BlackGanglion commented Apr 10, 2017

@BlackGanglion
Copy link
Owner Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant