1. 异步编程:
js是单线程事件循环。单线程就是:函数逐步运行的时候,要从上至下顺序执行。js引擎同一时刻只能执行一个代码块。这些代码块被准备执行都会加入任务队列。每段代码执行完毕,进入下一个代码块。
1.1. 事件模型:
当点击触发onClick等事件,会向任务队列增加一个新任务【代码块】相应操作。最基础的异步编程模式。
1.2. 回调模式:
与事件模型类似,函数会在未来某个时间点完成。区别是,回调模式的函数当做参数进行传入。(NodeJS错误优先原则)
缺点:
1. 但是如果回调函数嵌套过多,会先入回调地狱。
2. 如果想让两个异步操作,取得优先执`行完成的异步,这些操作将会难以完成。
2. Promise
概念:Promise是为异步操作的结果所准备的占位符。
2.1.Promise生命周期
- 挂起态(异步操作尚未结束)——>已决的(已经完成)1. 成功完成 2. 失败完成
- 我们不能直接获取promise对象的状态值,但是我们可以通过.then函数在Promise状态改变时执行 一些特定操作。
.then(函数1, 函数2)
第一个参数是成功时执行的函数,第二个参数是失败时执行的函数
.catch(函数1)
只传入执行失败的函数
有.then()
都是thenable函数。所有的Promise都是 thenable,但是不是所有的thenable都是promise
- promise的完成程序被调用,再在里面添加另一个完成处理程序,这个新的完成处理程序会被添加到任务队列中。
2.3.创建未完成的promise
new Promise(包含处理华promise的代码执行器(resolve函数, reject函数) {处理成功, resolve(结果), 执行不成功, reject(结果)})
执行器会立即执行!!!
对于任务编排没有了解过。
new Promise会立即执行,并且【猜测】是阻塞执行的。之后的.then是在promise函数完成之后才会调用。
2.4.创建已完成的promise
目的:想用Promise表示一个已知值,只是简单给resolve()函数传值。
- 创建已完成的成功promise
let pro = Promise.resolve(42);
pro.then(res => {console.log(res)});
当然,是我我肯定这样写
let pro = new Promise(function () { resolve(45)});
pro.then(res => {console.log(res)});
上一中方法写的好处永远不会存在拒绝状态
- 创建已完成的成功promise
let pro = Promise.reject(42);
pro.catch(res => {console.log(res)});
!!!如果向Pomise.resolve()方法或者 Promise.reject()方法传入一个Promise函数,那么这个Promsie函数会被直接返回。【理解,哪怕直接返回了,返回出来不也会立即执行吗,因为有执行器,而执行器会立即执行】
3.非Promise的Thenable函数
含义:拥有.then并且接受(resolve, reject)这两个参数作为普通对象
Promise.reject()和Promise.resolve()都可以接受非promise的thenable函数作为参数。并且这些方法会创建一个新的promise,并在.then函数中调用。
let thenAble = {
then : function(resolve, reject) {
resolve(43);
}
}
let testPro = Promise.resolve(thenAble);
testPro.then(res => {console.log(res)}); // 43
console.log('333333');
let testPro = Promise.resolve(
new Promise(function (resolve) {
console.log('1111111');
resolve('11111111')}
)
).then(res =>
console.log('2222222'+res)
);
console.log('444444444')
// 33333 11111 44444 22222111111 resolve会阻断 then不是阻断的
2.4.执行器错误
如果执行器内部抛出错误threw new Error('error')。Promise对象的.catch()方法会被调用。只有当拒绝处理程序存在时,才会在记录执行器抛出的错误,否则错误会被忽略掉。
【记录:在哪儿记录?console里面报错吗? 拒绝处理程序: reject函数么?】
3.全局的promise拒绝处理
promise.reject()不会进行报错,因为不知道他在什么时候进行这个报错处理。因此,没法进行强制报错。
3.1.NodeJS环境的拒绝处理
【看不明白,不知道事件循环,不了解nodeJS】
NodeJs中。处理promise拒绝时会触发process对象上的两个时间。
unhandledRejection 在事件循环【???】中,Promise被决绝,没有提供处理函数会触发事件。
rejectionHandled 若一个 Promise 被拒绝、并在事件循环的一个轮次之后再有拒绝处理函数被调用,该事件就会被触发。
将1. 拒绝原因 2. 被拒绝的promise作为参数被传入unhandledRejection
let rejected;
process.on("unhandledRejection", function(reason, promise) {
console.log(reason.message); // "Explosion!"
console.log(rejected === promise); // true
});
rejected = Promise.reject(new Error("Explosion!"));
3.2.浏览器的拒绝处理
4.串联的promise
每次调用.then()或者.catch()都返回了另一个Promise只有第一个完成才会进行第二个。
let p1 = new Promise(function(res, rej) {
res(42)
})
let p2 = p1.then(res => {
console.log(res);
})
p2.then(res => {
console.log(res);
})
思考: 既然是p2是promise 那样在哪儿resolve();的呢??让他可以.then。为什么不p2 resolve之后才能调用p2.then????
4.1.捕获错误
和上面相同原理。但是注意,不能一直向外抛出错误,总得解决掉他。
4.2.promise链的返回值
在.then中使用return语句,可以在下一个.then中拿到上一个return的值
4.3.promise链中返回promise
作用:给下游的promise返回值
p1.then(return 值).then(值 => {})
p2.catch(return 值).then(值 => {})
4.4.promise链中返回promise
体会:
let p1 = new Promise(function(resolve, reject){ console.log('111111111'); resolve(1) });
let p2 = new Promise(function(resolve, reject){ console.log('222222222'); resolve(2) });
let p3 = new Promise(function(resolve, reject){ console.log('333333333'); reject(3) });
let p4 = p1.then(res => {console.log(res); return p2});
let p5 = p4.then(res => {console.log(res); return p3});
let p6 = p5.catch(res => {console.log(res)});
p1.then()生成promise函数。之后p5.then()就是调用这个promise中的.then。至于为什么不是p2的promise,规定吧。当p3抛出错误,p5作为p3的包装的promise,当然应该能拿到。我是这样理解的。
5.响应多个Promise
Promise.all() / Promise.race()
5.1.Promise.all()
接收一个参数并返回Promise,该参数是含有多个受监视Promise的可迭代对象。只有当所有完成之后,才会执行all方法。当有一个拒绝,立马调用catch函数
let p1 = new Promise(function(resolve, reject){ console.log('111111111'); resolve(1) });
let p2 = new Promise(function(resolve, reject){ console.log('222222222'); resolve(2) });
let p3 = new Promise(function(resolve, reject){ console.log('333333333'); resolve(3) });
let p4 = Promise.all([p1, p2, p3]);
p4.then(val => {console.log(val)});
//111111111 222222222 333333333 (3) [1, 2, 3]
let p1 = new Promise(function(resolve, reject){ console.log('111111111'); resolve(1) });
let p2 = new Promise(function(resolve, reject){ console.log('222222222'); resolve(2) });
let p3 = new Promise(function(resolve, reject){ console.log('333333333'); reject(3) });
let p4 = Promise.all([p1, p2, p3]);
p4.then(val => {console.log(val)});
p4.catch(val => {console.log(val)});
// 111111111 222222222 333333333 3
5.2.Promise.race()
当有一个Promise被resolve就会被调用。传参方式相同。传入的res是第一个resolve的值。当一个执行完成的Promise的函数是被拒绝状态,
let p1 = new Promise(function(resolve, reject){ console.log('111111111'); setTimeout(() => {resolve(20)}, 1000) });
let p2 = new Promise(function(resolve, reject){ console.log('333333333'); reject(3) });
let p4 = Promise.race([p1, p2]);
p4.then(val => {console.log(val)}); // 这里没执行??
p4.catch(val => {console.log(val)});
//111111111 333333333 3
6.自Promse继承
// 类的继承吧