promise的目的:实现异步调用和解决回调多层嵌套的问题
一、promise是什么:promise是一个构造函数,但是不能被直接调用,只能通过new 执行,否则报 “TypeError: Promise constructor cannot be invoked without 'new'”.比如:proimse()就会报错。
构造数接收一个函数作为参数,返回一个promise对象:简单用法:
function executor(resovle,reject){
resovle(1)
}
let p= Promise(executor);
p.then(res=>{
console.log(res);
},err=>{
console.log(err);
})
Promise的3种状态:
1、pending ;
2、fulfilled
3、rejected
promise的特点:通过现象看本质
现象一:
function executor1(resovle, reject) {
resovle("成功")
reject("失败")
throw "error"
}
function executor2(resovle, reject) {
reject("失败")
resovle("成功")
throw "error"
}
function executor3(resovle, reject) {
throw "error"
reject("失败")
resovle("成功")
}
let p1 = new Promise(executor1);
let p2 = new Promise(executor2);
let p3 = new Promise(executor3);
console.log(p1);
console.log(p2);
console.log(p3);
结论:
1、状态一旦被改变就不可逆,执行的结果也是不可变的,状态只能从: pending->fulfilled 或者 pending->rejected 。
2、执行器函数内部抛出的异常:状态也是rejected,在promise里面的构造函数调用executor函数时,通过try...catch(e) 捕获了异常,在catch块里面执行了reject(e)方法。
现象二、then方法的调用和链式调用:
结果:
结论:
3、then 方法的参数只有函数才有效: then 方法接收2个可传参数,如果参数不传或者不是函数就会被忽略掉,请看30和31行代码。
4、then方法的回调函数的返回值做为下一次then的结果。
注:函数如果不写return,等价return undefined。
5、返回值可以向下传递:第三个then可以打印出第二个then的返回值。
6、then方法的返回值为非promise 对象。
问题1、37行的返回值是一个promise对象,为什么下一次then的回调不是promise对象?
7、执行器里面执行resolve回调then的一个函数,执行reject回调第二函数。
8、回调函数里面抛异常,执行下个then的第二个回调函数。 34行和36
现象三:catch方法
结论:
9、catch方法,等价于then(null,err=>{})
promise a plus文档: https://promisesaplus.com/
Promise的大概实现如下,只是实现了大概的思想,并没有完全遵守Promise A+的规范:
const PENDING = 'pending';
const Fulfilled = 'fulFilled';
const REJECTED = 'rejected';
export default class MyPromise {
constructor(executor) {
this.status = PENDING;
this.reason = undefined;
this.value = undefined;
this.fulFilledCallback = () => {};
this.rejectedCallback = () => {};
try {
executor(this.resolve, this.reject);
} catch (e) {
this.reject(e)
}
}
resolve = (res) => {
if (this.status === PENDING) {
this.status = Fulfilled;
this.value = res;
this.fulFilledCallback()
}
}
reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.rejectedCallback();
}
}
static resolve(res) {
return new myPromise((resovle, reject) => {
resovle(res)
})
}
static reject(res) {
return new myPromise((resovle, reject) => {
reject(res)
})
}
catch (res) {
return this.then(null, res)
}
then(onFulFilled, onRejected) {
onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : data => data;
onRejected = typeof onRejected === 'function' ? onRejected : err => {
throw err
};
let promise2 = new myPromise((resovle, reject) => {
if (this.status === Fulfilled) {
setTimeout(() => {
let x = onFulFilled(this.value)
resolvePromise(promise2, x)
})
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x)
} catch (e) {
reject(e)
}
})
}
if (this.status === PENDING) {
this.fulFilledCallback = () => {
let x = onFulFilled(this.value)
resolvePromise(promise2, x)
}
this.rejectedCallback = () => {
let x = onRejected(this.reason)
resolvePromise(promise2, x)
}
}
})
return promise2;
}
}
function resolvePromise(promise2, x) {
if (x instanceof myPromise) {
let then = x.then;
then.call(x, value => {
setTimeout(() => {
let v = getValueK(value);
resolvePromise(promise2, v)
})
}, err => {
promise2.reject(err)
})
} else {
promise2.resolve(x)
}
}
function getValueK(promise) {
if (promise instanceof myPromise) {
getValueK(promise.value)
} else {
return promise
}
}