Promise深入了解

Promise深入了解

一、promise基本使用

promise是js中进行异步编程的解决方案。

Promise 实例(用Promise封装异步操作):

resolve:解决 函数类型的数据

reject :拒绝 函数类型的数据

调用then方法:第一个参数 状态为成功的回调函数;第二个参数 状态为失败的回调函数

1. 读取文件(node环境)

const fs = require('fs');

//Promise 形式
let p = new Promise((resolve, reject) => {
    fs.readFile('./resource/content.txt', (err, data) => {
        if (err) reject(err);
        resolve(data);
    });
});
p.then(
    (value) => {
        console.log(value.toString());
    },
    (reason) => {
        console.log(reason);
    }
);

2. 发送请求

const p = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://127.0.0.1:8000/server');
    xhr.send();
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300)
                resolve(xhr.response);
            else {
                reject(xhr.status);
            }
        }
    };
});
p.then(
    (value) => {
        console.log(value);
    },
    (reason) => {
        console.warn(reason);
    }
);

二、Promise封装

1. 读取文件(node环境)

function mineReadFile(path) {
    return new Promise((resolve, reject) => {
        require('fs').readFile(path, (err, data) => {
            if (err) reject(err);
            resolve(data);
        });
    });
}
mineReadFile('./resource/content.txt').then(
    (value) => {
        console.log(value.toString());
    },
    (reason) => {
        console.log(reason);
    }
);

2. 发送请求

以下代码与平时开发用到的请求形式非常相似。

function sendAJAX(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.send();
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300)
                    resolve(xhr.response);
                else {
                    reject(xhr.status);
                }
            }
        };
    });
}
sendAJAX('http://127.0.0.1:8000/server').then(
    (value) => {
        console.log(value);
    },
    (reason) => {
        console.warn(reason);
    }
);

三、Promise的API

1. catch

let p = new Promise((resolve, reject) => {
    reject('error');
});

// catch方法用来指定失败的回调函数
p.catch((reason) => {
    console.log(reason);
});

2. resolve

// 传入参数为 非Promise类型的对象,则返回的结果为成功的promise对象
let p1 = Promise.resolve('521');
// 传入参数为 Promise 对象,则参数的结果决定了 resolve 的结果
let p2 = Promise.resolve(
    new Promise((resolve, reject) => {
        // resolve('ok');   //内部成功则外部也成功 且结果一样
        reject('err'); //内部失败则外部也失败
    })
);

3. reject

// 返回结果永远都是失败 传什么结果为什么
let p = Promise.reject('521');
let p1 = Promise.reject( // 结果为promise对象
    new Promise((resolve, reject) => {
        resolve('ok');
    })
);

4. all

let p1 = new Promise((resolve, reject) => {
    resolve('ok');
});
let p2 = new Promise((resolve, reject) => {
    resolve('Success');
});
let p3 = new Promise((resolve, reject) => {
    resolve('OHHHHH');
});
let p4 = new Promise((resolve, reject) => {
    reject('err');
});
const result = Promise.all([p1, p2, p3]); //全部成功则成功 返回值为所有成功结果的集合
const result1 = Promise.all([p1, p2, p4]); //有一个失败就失败 返回值为失败的结果
console.log(result);
console.log(result1);

请添加图片描述

5. race

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok');
    }, 1000);
});
let p2 = new Promise((resolve, reject) => {
    resolve('Success');
});
let p3 = new Promise((resolve, reject) => {
    resolve('OHHHHH');
});
// 谁先改变状态,则他的结果为返回值
const result = Promise.race([p1, p2, p3]);
console.log(result);

请添加图片描述

Promise对象有三种状态:

初始化状态:pending

resolve('ok'); pending -> fulfilled

reject('err'); pending-> rejected

四、promise创建实例简单实现

Promise构造函数参数为: executor函数 —— 执行器 ((resolve,reject)=>{})

executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行。

以最初的例子为例观察:

const p = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://127.0.0.1:8000/server');
    xhr.send();
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300)
                resolve(xhr.response);
            else {
                reject(xhr.status);
            }
        }
    };
});
p.then(
    (value) => {
        console.log(value);
    },
    (reason) => {
        console.warn(reason);
    }
);

1. 首先创建类

class Promise {
    constructor(executor) {
        function resolve(data) {
        }

        function reject(error) {
        }
        
        try {
            executor(resolve, reject);
        } catch (error) {
            //修改promise 状态为失败
            reject(error);
        }
    }
}

2. 在then中获取resolve、reject具体执行

这里类需要添加三个属性:对象状态对象结果值对象回调数组

且promise对象的then可以链式调用,所以then返回promise对象

class Promise {
    constructor(executor) {
        // 添加属性
        this.PromiseState = 'pending';
        this.PromiseResult = null;
        this.callbacks = [];

        const self = this;
        function resolve(data) {
            if (self.PromiseState !== 'pending') return;
            // 1. 修改对象的状态 (promiseState)
            self.PromiseState = 'fulfilled';
            // 2. 修改对象结果值 (promiseResult)
            self.PromiseResult = data;
            // 调用成功的回调函数,异步
            setTimeout(() => {
                self.callbacks.forEach((item) => {
                    item.onResolved(data);
                });
            });
        }

        function reject(data) {
            if (self.PromiseState !== 'pending') return;
            // 1. 修改对象的状态 (promiseState)
            self.PromiseState = 'rejected';
            // 2. 修改对象结果值 (promiseResult)
            self.PromiseResult = data;
            // 执行回调
            setTimeout(() => {
                self.callbacks.forEach((item) => {
                    item.onRejected(data);
                });
            });
        }

        try {
            executor(resolve, reject);
        } catch (error) {
            //修改promise 状态为失败
            reject(error);
        }
    }

    then(onResolved, onRejected) {
        const self = this;
        // 判断回调函数参数
        if (typeof onRejected !== 'function') {
            onRejected = (reason) => {
                throw reason;
            };
        }
        if (typeof onResolved !== 'function') {
            onResolved = (value) => value;
        }
        return new Promise((resolve, reject) => {
            // 封装函数
            function callback(type) {
                try {
                    // 获取回调函数的执行结果
                    let result = type(self.PromiseResult);
                    if (result instanceof Promise) {
                        result.then( // 支持链式调用,且结果传递
                            (v) => {
                                resolve(v);
                            },
                            (r) => {
                                reject(r);
                            }
                        );
                    } else {
                        resolve(result);
                    }
                } catch (error) {
                    reject(error);
                }
            }
            if (this.PromiseState === 'fulfilled') {
                setTimeout(() => {
                    //异步
                    callback(onResolved);
                });
            }
            if (this.PromiseState === 'rejected') {
                setTimeout(() => {
                    callback(onRejected);
                });
            }
            if (this.PromiseState === 'pending') {
                // pending状态保存回调函数
                this.callbacks.push({
                    onResolved: function() {
                        callback(onResolved);
                    },
                    onRejected: function() {
                        callback(onRejected);
                    },
                });
            }
        });
    }
}

分析:

若executor内的reject, resolve先于then执行,则改变对象状态,执行空回调函数数组。在p.then执行回调函数。

若executor内的reject, resolve后于then执行,则then收集回调函数,在executor内的reject, resolve执行回调函数。

五、async和await

1. async

函数返回值为Promise对象 结果由async函数执行的返回值决定

async function main() {
    // 1. 返回值为非Promise类型数据 返回结果为fulfilled 结果为返回值
    
    // 2. 返回一个Promise对象 结果和Promise的结果一致
    return new Promise((resolve, reject) => {
        // reject('err');
        resolve('ok');
    });
    
    // 3. 抛出异常 结果失败rejected 结果为抛出的值
    // throw 'Oh NO';
}

2. await

  1. await右侧的表达式一般为Promise对象,但也可以是其他值
  2. 如果表达式是Promise对象,await返回的是Promise成功的值
  3. 如果表达式是其他值,直接将此值作为await的返回值
  4. 注意:
    1. await必须写在async函数中,但async函数可以没有await
    2. 如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
async function main() {
    let p = new Promise((resolve, reject) => {
        reject('err');
    });
    
    try {
        let res = await p;
    } catch (error) {
        console.log(error);
    }
}
main();

一般用async和await同步处理异步操作。

综上,完成对Promise的梳理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值