为什么要用promise?
在promise前是用回调函数,当随着回调嵌套的越多会产生回调地狱的问题。
- 回调地狱是为了让我们代码执行顺序的一种操作(解决异步),但是它会使我们的可读性非常差。
基本概念 — 买包包示例
<script>
// promise 承诺
// 异步的
// 声明时状态是待定的,只有两种状态变换,待定->成功状态 和 待定->失败状态,状态都是不可逆转的
let isForget = false;
let getLv = new Promise((resolve, reject) => {
if(isForget){
let lv = {
color: 'red',
price: '¥99'
}
resolve(lv) // 成功状态
}else{
let err = new Error('我加班去了,忘记了')
reject(err) // 失败状态
}
})
let testFn = function (){
getLv.then((fulfilled)=>{ // then 表示成功状态
console.log(fulfilled);
}).catch((rejectd)=>{ // catach 表示失败状态
console.log(rejectd.message);
})
}
testFn()
</script>
promise的链式调用
<script>
// promise 承诺
// 异步的
// 声明时状态是待定的,只有两种状态变换,待定->成功状态 和 待定->失败状态,状态都是不可逆转的
let isForget = true;
let getLv = new Promise((resolve, reject) => {
if(isForget){
let lv = {
color: 'red',
price: '¥99'
}
resolve(lv) // 成功状态
}else{
let err = new Error('我加班去了,忘记了')
reject(err) // 失败状态
}
})
let buyLip = (lv)=>{
let lip = {
brand: 'w',
color: 'pink'
}
let msg = {
message: `我买的口红是${lip.brand}搭配我的${lv.color}`,
lip: lip,
lv: lv
}
return Promise.resolve(msg)
}
let testFn = ()=>{
getLv
.then(buyLip)
.then((fulfilled)=>{
console.log(fulfilled);
}).catch((rejectd)=>{
console.log(rejectd.message);
})
}
testFn()
</script>
手写一个Promise
- 基本结构
// 基本结构
<script>
function myPromise (excutor){ // excutor: 传入一个函数作为执行器
// 第一步 1.执行结构
let self = this;
self.status = 'pending'; // 状态
self.value = null; // 成功的结果
self.reason = null; // 失败的结果
// 成功的回调
function resolve(value){
}
// 失败的回调
function reject(reason){
}
// 第三步 3. 执行一遍 也可不加try catch 直接执行 excutor(resolve, reject)
// 预防出错外面包 try catch
try{
// 执行器
excutor(resolve, reject);
}catch(err){
reject(err)
}
// 第三步 3. 执行一遍
}
// 第二步 2. .then方法 -> 添加到原型链上
myPromise.prototype.then = function(){
}
let demo = new myPromise((resolve, reject)=>{
console.log('wzt');
})
</script>
- 基本功能 promise 1.0 版
<script>
function myPromise (excutor){ // excutor: 传入一个函数作为执行器
// 第一步 1.执行结构
let self = this;
self.status = 'pending'; // 状态
self.value = null; // 成功的结果
self.reason = null; // 失败的结果
// 第八步 8. 添加缓存数组
self.onFulfilledCallbacks = [];
self.onRejectedCallbacks = [];
// 成功的回调
function resolve(value){
// 第四步 4. 判断状态,做相应处理
if(self.status === 'pending'){
self.value = value; // 保存成功的结果
self.status = 'fulfilled' // 将状态变为成功状态
// 第十步 10. 状态改变,依次取出
self.onFulfilledCallbacks.forEach(item => item(value))
}
}
// 失败的回调
function reject(reason){
// 第四步 4. 判断状态,做相应处理
if(self.status === 'pending'){
self.reason = reason; // 保存失败的原因
self.status = 'rejected'
// 第十步 10. 状态改变,依次取出
self.onRejectedCallbacks.forEach(item => item(reason))
}
}
// 第三步 3. 执行一遍 也可不加try catch 直接执行 excutor(resolve, reject)
// 预防出错外面包 try catch
try{
// 执行器
excutor(resolve, reject);
}catch(err){
reject(err)
}
// 第三步 3. 执行一遍
}
// 第二步 2. .then方法 -> 添加到原型链上
myPromise.prototype.then = function(onFulfilled, onRejected){
// 第五步 5. 状态改变 => 调用then()
// 判断传入的是不是一个方法,如果是就用 如果不是就定义一个方法
onFulfilled = typeof onFulfilled === 'function' ?
onFulfilled : function (data) { resolve(data) }
onRejected = typeof onRejected === 'function' ?
onRejected : function (err) { throw err }
let self = this;
// 第九步 9. 先添加进去
if(self.status === 'pending'){
self.onFulfilledCallbacks.push(onFulfilled);
self.onRejectedCallbacks.push(onRejected);
}
}
let demo = new myPromise((resolve, reject)=>{
console.log('wzt');
// 第六步 6. 尝试异步任务
setTimeout(()=>{
resolve(11)
}, 500)
})
//
demo.then(data => console.log(data))
</script>
添加链式调用功能 promise 2.0 版
<script>
function myPromise (excutor){ // excutor: 传入一个函数作为执行器
// 第一步 1.执行结构
let self = this;
self.status = 'pending'; // 状态
self.value = null; // 成功的结果
self.reason = null; // 失败的结果
// 第八步 8. 添加缓存数组
self.onFulfilledCallbacks = [];
self.onRejectedCallbacks = [];
// 成功的回调
function resolve(value){
// 第四步 4. 判断状态,做相应处理
if(self.status === 'pending'){
self.value = value; // 保存成功的结果
self.status = 'fulfilled' // 将状态变为成功状态
// 第十步 10. 状态改变,依次取出
self.onFulfilledCallbacks.forEach(item => item(value))
}
}
// 失败的回调
function reject(reason){
// 第四步 4. 判断状态,做相应处理
if(self.status === 'pending'){
self.reason = reason; // 保存失败的原因
self.status = 'rejected'
// 第十步 10. 状态改变,依次取出
self.onRejectedCallbacks.forEach(item => item(reason))
}
}
// 第三步 3. 执行一遍 也可不加try catch 直接执行 excutor(resolve, reject)
// 预防出错外面包 try catch
try{
// 执行器
excutor(resolve, reject);
}catch(err){
reject(err)
}
// 第三步 3. 执行一遍
}
// 第二步 2. .then方法 -> 添加到原型链上
myPromise.prototype.then = function(onFulfilled, onRejected){
// 第五步 5. 状态改变 => 调用then()
// 判断传入的是不是一个方法,如果是就用 如果不是就定义一个方法
onFulfilled = typeof onFulfilled === 'function' ?
onFulfilled : function (data) { resolve(data) }
onRejected = typeof onRejected === 'function' ?
onRejected : function (err) { throw err }
let self = this;
// // 第九步 9. 先添加进去
// if(self.status === 'pending'){
// self.onFulfilledCallbacks.push(onFulfilled);
// self.onRejectedCallbacks.push(onRejected);
// }
if(self.status === 'fulfilled'){
return new myPromise((resolve, reject) => {
try{
let x = onFulfilled(self.value);
// 判断传进来的值是否是一个promise 是的话继续.then(), 否则抛出结果
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
}catch(err){
reject(err)
}
})
}
if(self.status === 'rejected'){
return new myPromise((resolve, reject) => {
try{
let x = onRejected(self.value);
// 判断传进来的值是否是一个promise 是的话继续.then(), 否则抛出结果
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
}catch(err){
reject(err)
}
})
}
if(self.status === 'pending'){
return new myPromise((resolve, reject) => {
self.onFulfilledCallbacks.push(()=>{
let x = onFulfilled(self.value);
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
});
self.onRejectedCallbacks.push(()=>{
let x = onRejected(self.value);
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
});
})
}
}
// 第十一步 11. .catch 方法 -> 添加到原型链上
myPromise.prototype.catch = function(fn){
return this.then(null, fn)
}
// *测试用例*******************************************************************************
// let demo = new myPromise((resolve, reject)=>{
// console.log('wzt');
// // 第六步 6. 尝试异步任务
// setTimeout(()=>{
// resolve(11)
// }, 500)
// })
// //
// demo.then(data => console.log(data))
let isForget = true;
let getLv = new myPromise((resolve, reject) => {
if(isForget){
let lv = {
color: 'red',
price: '¥99'
}
resolve(lv) // 成功状态
}else{
let err = new Error('我加班去了,忘记了')
reject(err) // 失败状态
}
})
let buyLip = (lv)=>{
let lip = {
brand: 'w',
color: 'pink'
}
let msg = {
message: `我买的口红是${lip.brand}搭配我的${lv.color}`,
lip: lip,
lv: lv
}
return new myPromise(function(y, n){
y(msg)
})
}
let testFn = ()=>{
getLv
.then(buyLip)
.then((fulfilled)=>{
console.log(fulfilled);
}).catch((rejectd)=>{
console.log(rejectd.message);
})
}
testFn()
</script>


