目录
Promise是什么
一种异步编程的解决方案;Promise本质来讲,可以理解为一个构造函数,我们必须通过new调用来创建Promise实例对象,它的参数是一个函数,这个参数函数参数分别是两个方法(表示成功,失败)。
个人理解,可以把其当作一口锅,我们在锅里做一系列等待结果的操作,最后到底是可口的饭菜还是黑黑的糊糊都由你自己决定
let p = new Promise((resolve,reject) => {
// 锅
// 做成了resolve
// 做失败reject
})
Promise的特点
- 有三个状态 pending(正在做-等待状态) fulfilled(做成了-成功状态) rejected(做废了-失败状态)。
- 状态不可变性,一旦状态发生改变本次状态结果就不会再变化(实现的时候希望能考虑到)- 可以通过类比做饭去记
Promise的作用
- 解决回调地狱问题,你需要理解then链式调用原理。(回调地狱)
- Promise可以处理并发请求,需要理解all race方法。
Promise方法介绍
实例方法 then
作用:监听成功和失败状态,以及获取结果
语法:
p.then((res) => {
// 成功 res结果是resolve()的参数
},(err) => {
// 失败
})
注意点:then的链式调用 -- 值得总结思考,在这里有一些规则(不确定正确,希望能自己去试)
规则1. 如果.then(()=> {}, () => {}) 中成功或者失败的回调不返回或者返回一个非promise值, 那么继续.then(() => {}), 监听到的是成功,获取的值就是返回的非promise值/undefined
规则2. 如果.then(()=> {}, () => {}) 中成功或者失败的回调返回的是一个 new Promise()实例 那么.then()监听到的就是返回的promise 值就是这个返回的Promise的返回值
规则3. 如果第一次.then中成功或者失败的回调返回的已经确定状态的Promise 例如 Promise.resolve() 那么继续.then()监听的就是成功 值的话就是参数 Promise.reject() 监听的就是失败 值的话就是参数
规则4. 如果第一次.then中成功或者失败的回调返回的是return new Error() --没有抛出 那么 继续 .then 监听的是成功 值就是error
规则5. 如果第一次。then回调throw抛出错误,那么继续.then监听到是失败
实例方法catch
作用:监听失败状态,获取失败信息
语法:
p.catch(err => {
console.log(err);
})
注意点:可与then配合链式调用
静态方法 resolve()
语法:
Promise.resolve()
作用:显式返回成功
注意点:参数若是一个Promise实例,那么结果如何值得思考
静态方法 reject()
语法:
Promise.reject()
作用:显式返回失败
注意点:参数若是一个Promise实例,那么结果如何值得思考
静态方法 race
语法:
Promise.all([p1,p2])
作用:串行 -- 参数是Promise实例组成的数组,记住第一个完成的状态就是结果状态,返回的结果就是最终结果
静态方法 all -- ****
语法:
Promise.all([p1,p2])
作用:并行 -- 记住数组中所有实例都成功则结果状态才成功,结果是每个成功结果组成的数组
Promise应用场景
- Axios发送请求
- 对于Ajax异步获取信息,如获取百度天气信息
- 操作数据库
Promise简单实现以及对完整实现的考虑方向
简单实现
/**简易版 不考虑连续.then
* 1. 搭建框架
* 2. try catch执行callback -- 捕获到错误也是失败
* 3. 定义resolve reject
* 4. 明白resolve reject 是干什么
* * 拒绝状态再次改变
* * 改变状态 -- 得有状态
* * 赋值结果 -- 得有结果
* * 执行异步改变状态存到队列中的回调 -- 得有队列
* 5. 明白then做了什么 -- 简易版不考虑连续.then -=- 也就是不需要考虑回调的返回值
* * 返回的是promise对象
* * 判断状态 执行相应回调
* * pending下 存到队列
* 6. 明白catch做了什么
* * 直接采用then处理函数参数
* 7. 考虑resolve
* * 返回promise
* * 如果参数是promise实例 状态看参数promise结果
* * 如果参数不是promise实例 肯定是成功状态
* 8. 考虑reject
* * 返回promise
* * 不论参数是啥 反正都是失败
* 9. 考虑all
* * 返回promise
* * 遍历看 所有都成功 才是成功 且结果是成功结果组成的数组
* 10.考虑 race
* * 返回promise
* * 第一个的状态就是结果的状态 也是结果的结果
*/
function Promise(callback) {
this.promiseState = "pending";
this.promiseResult = null;
this.callBackArr = [];
let resolve = (val) => {
if (this.promiseState !== "pending") return;
this.promiseState = "fulfilled";
this.promiseResult = val;
this.callBackArr.forEach((item) => {
item.onResolved(val); // 此时也不考虑回调返回值
});
};
let reject = (val) => {
if (this.promiseState !== "pending") return;
this.promiseState = "reject";
this.promiseResult = val;
this.callBackArr.forEach((item) => {
item.onRejected(val); // 此时也不考虑回调返回值
});
};
try {
callback(resolve, reject);
} catch (error) {
reject(err);
}
}
Promise.prototype.then = function (onResolved, onRejected) {
return new Promise((resolve, reject) => {
// 暂时不考虑.then结果
if (this.promiseState == "fulfilled") {
// 因为.then是异步的 所以回调的执行得在同步之后
setTimeout(() => {
onResolved(this.promiseResult); // 回调的结果先不考虑
});
}
if (this.promiseState == "rejected") {
setTimeout(() => {
onRejected(this.promiseResult);
});
}
// 异步改变状态 回调在改变状态后执行
if (this.promiseState == "pending") {
this.callBackArr.push({
onResolved,
onRejected,
});
}
});
};
Promise.prototype.catch = function (onRejected) {
this.then(undefined, onRejected);
};
Promise.resolve = function (data) {
return new Promise((resolve,reject) => {
if(data instanceof Promise) {
data.then(res => {
resolve(res)
}, err => {
reject(err)
})
}else {
resolve(data)
}
})
};
Promise.reject = function (data) {
return new Promise((resolve, reject) => {
reject(data)
})
};
Promise.all = function (arr) {
return new Promise((resolve, reject) => {
let result = [], count = 0
for (let i = 0; i < arr.length; i++) {
arr[i].then((res) => {
count++
result[i] = res
}, (err) => {
reject(err)
})
}
if(count == arr.length) {
resolve(result)
}
});
};
Promise.race = function (arr) {
return new Promise((resolve,reject) => {
for(let i = 0; i < arr.length; i++) {
arr[i].then((res) => {
resolve(res)
}, err => {
reject(err)
})
}
})
};
可以再具体考虑.then情况,加油!
本文引用:
JavaScript中的回调地狱及解决方法 - wenxuehai - 博客园 (cnblogs.com) --- 介绍回调地狱