JS是单线程的:大部分代码都是同步的,但是也有少部分代码是异步编程的
- 异步宏任务
- 定时器
- ajax:一般都是异步的
- 事件绑定
异步微任务
是什么:异步编程解决方案,ES6内置类,承诺模式
- 干什么:
- 有了
Promise
对象,就可以将异步操作以同步操作的流程(链式调用)表达出来,避免了层层嵌套的回调函数(回调地狱)。 - 此外,
Promise
对象提供统一的接口,使得控制异步操作更加容易。
- 有了
_let p = new Promise([executor]);_
- [executor]:可执行函数
- new Promise的时候,在Promise内部会立即把[executor]函数执行(同步的)
- 函数中一般用来管理一个异步编程代码(不管控异步编程也是可以的)
- 同时给[executor]函数传递两个值「函数类型」:resolve / reject
p 是Promise类的一个实例, 可以在里面chrome调试器里直接看到的东西,可以直接学习
在[executor]执行 resolve / reject 都是为了改变 promise实例 的状态和值「结果」
一但状态被改变成 fulfilled / rejected 则不能再改为其他的状态
- resolve(‘OK’);
[[PromiseState]]:fulfilled
[[PromiseResult]]:'OK'
- reject(‘NO’);
[[PromiseState]]:rejected
[[PromiseResult]]:'NO'
- resolve(‘OK’);
如果[executor]函数执行执行出错,则
[[PromiseState]]:rejected
[[PromiseResult]]:报错原因
- Promise内部做了异常信息捕获「try/catch」
实例状态的改变,可以控制,执行then方法时,存放的两个方法中的某一个方法执行
p.then(onfulfilledCallback, onrejectedCallback)
- 状态成功执行的是:
onfulfilledCallback
- 状态失败执行的是:
onrejectedCallback
```javascript let p1 = new Promise((resolve, reject) => { reject(‘NO’); });
p1.then(result => { console.log(‘成功—>’, result); }, reason => { console.log(‘失败—>’, reason); });
p1.then(result => { console.log(‘成功—>’, result); }, reason => { console.log(‘失败—>’, reason); });
<a name="wDVvR"></a>
## 同步异步?
1. 执行`**p.then(onfulfilledCallback,onrejectedCallback)**`
1. 首先把传递进来的`onfulfilledCallback`和`onrejectedCallback`存储起来「存储在一个容器中:因为可以基于then给其存放好多个回调函数」
1. 其次再去**验证当前实例(p)的状态**
1. 如果实例状态是 `pending`,则不做任何的处理
1. 如果已经变为`fulfilled`/`rejected`,则会通知对应的回调函数执行
1. 但是**不是立即执行**,而是把其放置在EventQueue中的**微任务队列**中
**promise本身不是异步的**,**是用来管理异步的**<br />**但是then方法是异步的「微任务」**
例一:
```javascript
let p = new Promise((resolve, reject) => {
console.log(1);
resolve('OK'); //=>同步修改其状态和结果
console.log(2);
});
console.log(p); //此时状态已经修改为成功...
// 不是立即执行,而是把其放置在EventQueue中的微任务队列中
p.then(result => {
console.log('成功-->', result);
});
console.log(3);
// 同步执行完了,再在微任务队列里执行里面的东西
例二:
刚开始打印:
1000ms之后:
resolve
- resolve值和状态的改变是同步的
- 但是通知then方法存放的
onfulfilledCallback
执行则是异步的 - 我们也可以说,promise的异步也来源于resolve和reject
let p = new Promise((resolve, reject) => {
console.log(1);
setTimeout(() => {
resolve('OK');
// + 改变实例的状态和值「同步」
// + 通知之前基于then存放的onfulfilledCallback执行「异步的微任务:也是把执行方法的事情放置在EventQueue中的微任务队列中」
console.log(p);
console.log(4);
}, 1000); //=>存储了一个异步的宏任务
console.log(2);
});
console.log(p);
// 此时接受onfulfilledCallback的时候,状态还是pending,此时只把方法存储起来
p.then(result => {
console.log('成功-->', result);
});
console.log(3);
// 等1000ms后,执行定时器中的函数「把异步宏任务拿出来执行」
then的链式调用
执行then方法会返回一个全新的promise实例p2
- p2的状态和值是咋改变的?
- 不论执行的是基于p1.then存放的
onfulfilledCallback
/onrejectedCallback
两个方法中的哪一个- 只要方法执行不报错
- 如果方法中返回一个全新的Promise实例,则“全新的Promise实例”的成功和失败决定p2的成功和失败
- 如果不是返回promise呢?则
[[``PromiseState``]]:``fulfiled`` [[``PromiseResult``]]:返回值
- 如果方法执行报错:p2的 [[PromiseState]]:rejected [[PromiseResult]]:报错原因
- 只要方法执行不报错
promise实例 的状态和值目前改变方法:
- 本身:
- resolve / reject 的执行
- resolve执行是否报错
- then方法相关
- then 方法中返回的promise实例情况
Promise.reject(10);
Promise.resolve(10);
- 不返回promise
[[``PromiseState``]]:``fulfiled
[[``PromiseResult``]]:返回值
- then 两个方法执行是否报错
- then 方法中返回的promise实例情况
注意!!p2的状态和p1成功失败没关系:就算p1失败了,但里面没报错,也没返回reject的promise,p2就不会是失败的
let p1 = new Promise((resolve, reject) => {
resolve('OK');
// reject('NO');
});
let p2 = p1.then(result => {
console.log('P1成功-->', result);
return Promise.reject(10);
}, reason => {
console.log('P1失败-->', reason);
});
let p3 = p2.then(result => {
console.log('P2成功-->', result);
}, reason => {
console.log('P2失败-->', reason);
return Promise.resolve(10);
});
p3.then(result => {
console.log('P3成功-->', result);
}, reason => {
console.log('P3失败-->', reason);
return Promise.resolve(10);
});
console.log(1);
- 顺延机制
- 如果onfulfilledCallback/onrejectedCallback不传递,则状态和结果都会“顺延/穿透”到下一个同等状态应该执行的回调函数上「内部其实是自己补充了一些实现效果的默认函数」
- result=> result
- reason=> Promise.reject(reason) ```javascript
- 如果onfulfilledCallback/onrejectedCallback不传递,则状态和结果都会“顺延/穿透”到下一个同等状态应该执行的回调函数上「内部其实是自己补充了一些实现效果的默认函数」
new Promise((resolve, reject) => { // resolve(‘OK’); reject(‘NO’); }).then(null, reason=>{ // 这里传null, console.log(‘失败—>’,reason); }).then(result => { console.log(‘成功—>’, result); }, reason => { console.log(‘失败—>’, reason); }).then(result => { console.log(‘成功—>’, result); }, reason => { console.log(‘失败—>’, reason); });
catch只处理状态为失败下做的事情
```javascript
Promise.prototype.catch = function (onrejectedCallback) {
return this.then(null, onrejectedCallback);
};
then只放成功,catch放失败
后盾人的一道题
async function hd(num) {
let res = await Promise.resolve().then(() => {
let count = 0;
debugger
for (let i = 0; i < num; i++) {
count += num--
}
return count
})
console.log(res);
}
hd(3125651) //这个函数是为了出来大量计算 但又不想影响主线程后面的输出 所以用了.then异步的微任务特性
console.log('后盾人');