Promise系列总结

Promise操作是为了解决异步回调地狱问题:
// 应用场景:将下面三个异步方法控制先后执行顺序
import axios from 'axios'
#PS:除了下面created说明的两种方法还可以使用new Promise统一封装请求、然后使用async/await搭配同步化宏任务代码
created() {
    // 方法一:
	this.axiosOne().then(res => {
        console.log('方法一:', res)
        return this.axiosTwo()
    }).then(res => {
        console.log('方法二:', res)
        return this.axiosThree()
    }).then(res => {
        console.log('方法三:', res)
    })
     // 方法二:
     // return new Promise(async (resolve, reject) => {
     //   const { status: r1 } = await this.axiosOne()
     //   r1 === 200 && resolve()
     //   const { status: r2 } = await this.axiosTwo()
     //   r2 === 200 && resolve()
     //   await this.axiosThree()
     // })
},
methods() {
    axiosOne() {
		return axios.get('https://jsonplaceholder.typicode.com/todos?_limit=5')
	},
	 axiosTwo() {
		return axios.get('https://jsonplaceholder.typicode.com/comments?_limit=5')
	},
	 axiosThree() {
		return axios.get('https://jsonplaceholder.typicode.com/albums?_limit=5')
	}
}
Promise封装请求
1.promise 封装axios(针对get)
export const request = (url, params={}) => {
    return new Promise(async(resolve, reject) => {
     	const res = await axios.get(url, {params})
     	if (res.code == 200) {
         	resolve(res.data)
     	} else {
            reject(res.data.msg)
        }
    })
}
2、promise 封装原生AJAX
let request = function (url,type="GET",data="") { 
        return new Promise((resolve,reject)=>{
            var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : ActiveXObject("microsoft.XMLHttp")
        xhr.open(type,url,true);
        xhr.send();
        xhr.onreadystatechange = () =>{
            if(xhr.readyState == 4){
                if(xhr.status == 200){
                    resolve(JSON.parse(xhr.response))
                }
            }
        }    
        })
     }
3、promise 封装原生$.ajax()
let request = function (url,type="GET",data="") { 
        return new Promise((resolve,reject)=>{
            $.ajax({
                url,
                type,
                data,
                success(res){
                    resolve(res)
                },
                error(res){
                    reject(res)
                }
            })
        })
     }
4、promise 封装原生fetch
return new Promise(function (resolve, reject) {  
      fetch(url, {  
            method: 'GET',  
            headers: headers,  
          })  
          .then((response) => {  
              if (response.ok) {  
                  return response.json();  
              } else {  
                  reject({status:response.status})  
              }  
          })  
          .then((response) => {  
              resolve(response);  
          })  
          .catch((err)=> {  
            reject({status:-1});  
          })  
    })  

Promise原理

// promise (原理代码)
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) { // 接收执行器
        try {
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e);
        }
    }
    
    status = PENDING; // promise的状态
    value = undefined; // 成功之后的值
    reason = undefined; // 失败之后的值
    successCallback = []; // 成功回调
    failCallback = []; // 失败回调
 
    // resolve和reject为什么要用箭头函数?
    // 如果直接调用的话,普通函数this指向的是window或者undefined
    // 用箭头函数就可以让this指向当前实例对象
    resolve = value => {
        // 如果状态不是等待 组织程序向下执行
        if (this.status !== PENDING) return
        // 将状态更改为成功
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在 调用
        //this.successCallback && this.successCallback(this.value)
        while (this.successCallback.length) this.successCallback.shift()()
    }
    reject = reason => {
        // 如果状态不是等待 组织程序向下执行
        if (this.status !== PENDING) return
        // 将状态更改为失败
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
        // 判断失败回调是否存在 如果存在 调用
        // this.failCallback && this.failCallback(this.reason)
        while (this.failCallback.length) this.failCallback.shift()();
    }
 
    then(successCallback, failCallback) {
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : reason => {
            throw reason
        }; // then链式调用参数变为可选参数 例:promise.then().then().then((value)=>{console.log(value)}) // value
        let promise2 = new MyPromise((resolve, reject) => {
            // 传递一个执行器 立马执行
            // 判断状态
            if (this.status === FULFILLED) {
                setTimeout(() => { // 将下面的代码变成异步代码
                    try {
                        let x = successCallback(this.value)
                        // 判断 x 的值是普通值还是promise对象
                        // 如果是普通值 直接调用resolve
                        // 如果是promise对象 查看promise对象返回的结果
                        // 再根据promise对象返回的结果 界定调用resolve 还是reject
                        resolvePromise(x, resolve, reject);
                    } catch (e) { // 处理异常状态
                        reject(e)
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => { // 将下面的代码变成异步代码
                    try {
                        let x = failCallback(this.reason)
                        resolvePromise(x, resolve, reject);
                    } catch (e) { // 处理异常状态
                        reject(e)
                    }
                }, 0)
            } else {
                // 当前状态是等待
                // 将成功回调和失败回调存储起来 - 多个then方法调用
                this.successCallback.push(() => {
                    setTimeout(() => { // 将下面的代码变成异步代码
                        try {
                            let x = successCallback(this.value);
                            resolvePromise(x, resolve, reject);
                        } catch (e) { // 处理异常状态
                            reject(e)
                        }
                    }, 0)
                });
                this.failCallback.push(() => {
                    setTimeout(() => { // 将下面的代码变成异步代码
                        try {
                            let x = failCallback(this.reason);
                            resolvePromise(x, resolve, reject);
                        } catch (e) { // 处理异常状态
                            reject(e)
                        }
                    }, 0)
                });
 
            }
        });
        return promise2;
    }
 
    finally(callback) {
        /**
         - 无论当前最终状态是成功还是失败,finally都会执行
         - 我们可以在finally方法之后调用then方法拿到结果
         - 这个函数是在原型对象上用的
         * **/
        return this.then(value => {
            return MyPromise.resolve(callback()).then(() => value)
        }, reason => {
            return MyPromise.resolve(callback()).then(() => {
                throw reason
            })
        })
    }
 
    catch(failCallback) {
        /**
         - catch方法是为了捕获promise对象的所有错误回调的
         - 直接调用then方法,然后成功的地方传递undefined,错误的地方传递reason
         - catch方法是作用在原型对象上的方法
         * **/
        return this.then(undefined, failCallback);
    }
 
    static all(array) {
        /**
         * 分析一下:
         - all方法接收一个数组,数组中可以是普通值也可以是promise对象
         - 数组中值得顺序一定是我们得到的结果的顺序
         - promise返回值也是一个promise对象,可以调用then方法
         - 如果数组中所有值是成功的,那么then里面就是成功回调,如果有一个值是失败的,那么then里面就是失败的
         - 使用all方法是用类直接调用,那么all一定是一个静态方法
         **/
        let result = [];
        let index = 0;
        return new MyPromise((resolve, reject) => {
            function addData(key, value) {
                // 保存每个传入参数执行完毕,并存储返回值
                result[key] = value;
                index++;
                if (index === array.length) {
                    resolve(result)
                }
            }
 
            for (let i = 0; i < array.length; i++) {
                let current = array[i];
                if (current instanceof MyPromise) {
                    // promise对象
                    current.then(value => addData(i, value), reason => reject(reason))
                } else {
                    // 普通值
                    addData(i, array[i])
                }
            }
        })
    }
 
    static resolve(value) {
        /**
         resolve方法的作用是将给定的值转换为promise对象 resolve的返回值的promise对象
         如果参数就是一个promise对象,直接返回,如果是一个值,那么需要生成一个promise对象,把值进行返回
         是Promise类的一个静态方法
         * **/
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value))
    }
}
 
function resolvePromise(x, resolve, reject) {
    if (x instanceof MyPromise) {
        // promise 对象
        // x.then( value => resolve(value),reason => reject(reason))
        x.then(resolve, reject)  // 简化
    } else {
        // 普通值
        resolve(x)
    }
}
 
module.exports = MyPromise;
// https://www.jianshu.com/p/fc5030e725ae (手写Promise)
function Promise(executor){ //executor执行器
    let self = this;
    self.status = 'pending'; //等待态
    self.value  = undefined; // 表示当前成功的值
    self.reason = undefined; // 表示是失败的值
    function resolve(value){ // 成功的方法
        if(self.status === 'pending'){
            self.status = 'resolved';
            self.value = value;
        }
    }
    function reject(reason){ //失败的方法
        if(self.status === 'pending'){
            self.status = 'rejected';
            self.reason = reason;
        }
    }
    executor(resolve,reject);
}

Promise.prototype.then = function(onFufiled,onRejected){
    let self = this;
    if(self.status === 'resolved'){
        onFufiled(self.value);
    }
    if(self.status === 'rejected'){
        onRejected(self.reason);
    }
}
module.exports = Promise;

Promise手写 .all( )方法 ( myAll )

// 定义几个Promise实例、用来测试
const p1 = Promise.resolve('----成功p1')

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('----p2 延时1s')
  }, 1000)
})

const p5 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('----p5 延时3s')
  }, 3000)
})

const p4 = Promise.reject('----失败p4')




// 实现和Promise.all功能一致
Promise.prototype.myAll = function(Arr) {
    let arr = [], count = 0;
    return new Promise((resolve, reject) => {
        Arr.forEach((item, i) => {
            Promise.resolve(item).then(res => {
                arr[i] = res
                count += 1
                if (count === Arr.length) { resolve(arr) } 
            }).catch(reject)
        })
    })
}


// 由于Promise.all()、catch后不会返回成功的结果
# 解决办法如下:
// 失败之后、也会返回成功的结果
let reqArr = [p1, p4, p2]

let transPromise = reqList => {
    return reqList.map(item => {
        return item.then(res => res).catch(err => err)
    })
}

let promiseArr = transPromise(reqArr)
Promise.all(promiseArr).then(resArr => {
    console.log(resArr)
})


// 手写Prommise.taoAll()、实现在有Prommise.all()的功能之上、catch之后也会返回成功和失败的结果
Promise.taoAll = params => {
  let arr = []
  let count = 0
  let r = params.map(row => row.then(res => res).catch(err => err))
  return new Promise((resolve, reject) => {
    r.forEach((item, i) => {
      Promise.resolve(item).then(res => {
        arr[i] = res
        count++
        count == params.length && resolve(arr)
      })
    })
  })
}

Promise.taoAll([p1, p4, p2]).then(res => console.log(res))

Promise三种状态

pedding、resolved(fulfilled)、rejected

使用Promise.all( )其中一个接口挂了你会如何处理

Promise.allSettled()
https://blog.csdn.net/xiaoleiv9/article/details/124456910

Promise.allSettled()

// 该方法和all()方法使用相似、区别在于这个方法无论状态返回是 rejected 还是 fulfilled、都会执行.then()的第一个回调、返回一个数组
# fulfilled时,对象有value属性,rejected时有reason属性,
const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);

const allSettledPromise = Promise.allSettled([resolved, rejected]);

allSettledPromise.then(function (results) {
  console.log(results);
});
// [
//    { status: 'fulfilled', value: 42 },
//    { status: 'rejected', reason: -1 }
// ]



# 例子:
const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
const results = await Promise.allSettled(promises);

// 过滤出成功的请求
const successfulPromises = results.filter(p => p.status === 'fulfilled');

// 过滤出失败的请求,并输出原因
const errors = results
  .filter(p => p.status === 'rejected')
  .map(p => p.reason);

Promise.all()

Promise.all(),发起多个并发请求,然后在所有 promise 都被解决后执行一些操作。

// 解构赋值语法也可以执行:
Promise.all([getUserAccount, getUserPermissions]).then(([res1, res2]) => {
  console.log('结果', res1, res2)
})

Promise.race( )方法、Promise.race赛跑机制,只认第一名

# race()方法 和 all() 方法类似、区别在于race()任意一个执行完成就算完成
// race的用法是:传入多个promise实例,谁跑的快,就以谁的结果执行回调

const first = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, '第一个')
})
const second = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, '第二个')
})

Promise.race([first, second]).then(result => {
  console.log(result) // 第二个
})

# 应用场景: 
1.定时器 和 异步操作(请求)放一起、如果定时器先触发、则认为超时、告知用户
function timeOut(time) {
    let result = new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve("请求超时")
        }, time) // 为了验证方法,可以把时间设小点
    });
    return result;
}

Promise.race([timeOut(200), fetch('https://api.github.com/users/ruanyf')]).then(res => {
    console.log(res);
})

2.如果指定时间内没有获得结果,就将 Promise 的状态变为reject,否则变为resolve。
const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);

p
.then(console.log)
.catch(console.error);

Promise.resolve( )

// 将现有的对象转成 Promise对象
Promise.resolve('111').then((res) => { console.log(res) })

# 它的参数分四种情况
1.参数是一个 Promise实例、Promise.resolve()不会做任何修改、直接返回这个实例

2.参数是一个thenable对象(thenable对象:指的是对象里有then方法的对象)例:
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};
Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

3.参数不是具有then方法的对象,或根本就不是对象 (返回一个resolved状态的Promise对象)
const p = Promise.resolve('Hello');
p.then(function (s){
  console.log(s) // Hello
});

4.不带有任何参数
// Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。
const p = Promise.resolve();
p.then(function () {
  // ...
});

Promise.reject( )、它的参数会作为 reject 的理由、这一点 和 resolve不一样

// 返回一个rejected状态的实例
Promise.reject('失败').catch((err) => {
    console.log(err)  // '失败'
})

Promise.catch( )

Promise.catch((err) => err)

级联错误

// 如果在 catch() 内部引发错误,则可以附加第二个 catch()来处理,依此类推。
new Promise((resolve, reject) => {
  throw new Error('错误')
})
.catch(err => {
  throw new Error('错误')
})
.catch(err => {
  console.error(err)
})

Promise.then( )的第二个参数

// 第二个参数是一个抛出异常函数、(不建议这样使用、如果要抛出异常推荐总是用 catch() 方法)
# 理由: catch()写法可以捕获到前面 then方法执行中的错误、更接近 try/catch 写法
Promise.then((res) => {}, (err) => err)

Promise.finally( )

// finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

# 由于无法知道promise的最终状态,所以finally的回调函数中不接收任何参数,它仅用于无论最终结果如何都要执行的情况。

Promise相关应用场景总结参考:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只管挖坑不管埋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值