ES6——Promise

本文详细介绍了ES6中的Promise,包括异步编程背景、回调地狱问题、Promise的基本概念、状态与结果、API用法,以及手写Promise和async/await的使用。通过实例解析了Promise串联任务、异常处理和链式操作终止。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、异步编程:

  1. fs 文件操作
require('fs').readFile('./index.html',(err,data)=>{})
  1. AJAX
$.get('./server',(data)=>{})
  1. 数据库操作
  2. 定时器
setTimeout(()=>{},1000)

二、地狱回调问题

概念:回调函数嵌套,外部回调函数异步执行的结果是嵌套的回调函数的执行条件。
在这里插入图片描述

三、Promise介绍与使用

promise是异步编程的新的解决方案(ES6规范),它是一个构造函数。
可以实例化对象,封装异步操作,获取成功和失败的结果。
优点:支持链式调用,可以解决地狱回调问题,执行的方式更为灵活。

promise初体验——抽奖

<body>
    <div class="container">
        <h2 class="page-header">promise初体验</h2>
        <button class="btn btn-primary" id="btn">点击抽奖</button>
    </div>
    <script>
        function rand(m, n) {
            return Math.ceil(Math.random() * (n - m + 1)) + m - 1;
        }
        const btn = document.querySelector("#btn");
        btn.addEventListener('click', function () {
            // setTimeout(()=>{
            //     let n=rand(1,100);
            //     if(n<=30){
            //         alert("中奖了");
            //     }else{
            //         alert("再接再厉");
            //     }
            // },1000);
            
            // promise形式
            const p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    let n = rand(1, 100);
                    if (n <= 30) {
                        resolve(n);
                    } else {
                        reject(n);
                    }
                }, 1000);
            })
            p.then((data) => {
                alert(`中奖了,数字为${data}`);
            }, (data) => {
                alert(`再接再厉,数字为${data}`);
            })
        });
    </script>
</body>

promise实践练习——AJAX请求

    <script>
        const btn = document.querySelector("#btn");
        btn.addEventListener('click', function () {
            const p = new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.open('GET', 'https://api.apiopen.top/getJoke');
                xhr.send();
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 && xhr.status < 300) {
                            resolve('成功');
                        } else {
                            reject('失败');
                        }
                    }
                }
            })
            p.then((data) => {
                console.log(data);
            }, (err) => {
                console.log(err);
            })
        })
    </script>

promise实践练习——fs文件读取

    <script>
        const fs = request('fs');
        
        //回调函数形式
        // fs.readFile('./resource/content.txt',(err,data)=>{
        //     if(err){
        //         throw err;
        //     }else{
        //         console.log(data.toString());
        //     }
        // })

        //promise形式
        let p = new Promise((resolve, reject) => {
            fs.readFile('./resource/content.txt', (err, data) => {
                if (err) {
                    reject(data);
                }
                resolve(err);
            });
        })

        p.then((data) => {
            console.log(data.toString());
        }, (err) => {
            console.log(err);
        });
    </script>

四、promise对象的状态——PromiseState

实例对象中的一个属性 『PromiseState』,状态只能改变一次。

* pending  未决定的
* resolved / fullfilled  成功
* rejected  失败

五、promise对象的结果——PromiseResult

实例对象中的另一个属性 『PromiseResult』
保存着异步任务『成功/失败』的结果

六、promise的API

(1)promise构造函数可以通过 new 实例化对象

  • Promise(executor){}
  • 参数:executor执行器——(resolve,reject)=>{}

(2)Promise.prototype.then((onResolved,onRejected)=>{});

  • 参数返回结果是:throw ‘error’;则最终的promise就是一个失败的promise对象。
  • 参数返回结果是非promise对象:return 521;则最终的promise就是一个成功的promise对象,promiseState结果为521。
  • onResolved() 返回结果是promise对象:return Promise.resolve(521);则最终的promise就是一个成功的promise对象,promiseState结果为521。
  • onRejected() 返回结果是promise对象:return Promise.reject(521);则最终的promise就是一个失败的promise对象,promiseState结果为521。
   var p = new Promise((resolve, reject)=>{
            resolve('ok');
        });
        let result = p.then((value) => {
        	//1.抛出错误
            // throw '出问题了';
            //2.返回一个非Promise类型的对象
            // return 521;
            //3.返回一个Promise类型的对象
            return Promise.resolve(521);
            // return new Promise((resolve, reject)=>{
            //     //resolve('ok');
            //       reject('error');
            // })
        })
        console.log(result);

(3)Promise.prototype.catch((onRejected)=>{});
(4)Promise.resolve((value)=>{});

  • Promise函数对象上的方法,不是实例对象上的方法。
  • 如果参数为非promise对象,返回结果为成功的promise对象。
  • 如果参数为promise对象,参数的结果决定了resolve()返回的结果。

(5)Promise.reject((err)=>{});

  • Promise函数对象上的方法,不是实例对象上的方法。
  • 始终返回一个失败的promise对象;
  • 传入什么,PromiseResult就是什么;

(6)Promise.all((promises)=>{})

  • promises:是一个数组,包含n个promise
  • 返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败就直接失败。

(7)Promise.race((promises)=>{})

  • promises:是一个数组,包含n个promise
  • 返回一个新的promise,第一个改变promise的结果状态就是最终的结果状态。

七、promise的关键问题

1.如何改变promise对象的状态?

resolve()
reject()
throw 'error';

2.当一个promise制定了多个成功或失败的回调,都会执行吗?
答:对应状态的回调函数都会执行
3.改变promise状态和指定回调函数哪个先哪个后?
答:都有可能。一般都是先指定回调再改变状态。

  • 如何先指定回调再改变状态?
    答:改变状态调用resolve()为异步任务时(添加延时器)
  • 如何先改变状态再指定回调?
    (1)直接同步调用resolve()/reject();(同步任务)
    (2)延迟调用then()方法。
  • 什么时候能得到数据?
    答:回调函数调用后就会得到数据。

4.promise如何串联多个任务?(重点

 var p = new Promise((resolve, reject)=>{
       setTimeout(()=>{
            resolve('ok');
        },2000);
 });
 p.then((value)=>{
	 return new Promise((resolve,reject)=>{
			resolve('success');
	 })
 })//返回一个成功的promise对象,状态为成功,结果值为success
 .then(value=>{
 	console.log(value);//success
 })//value为上一层返回的结果值,即一个成功的promise对象,成功的结果值为:success,则输出的结果就为:success,且本身的then()方法无返回值。
 .then(value=>{
 	console.log(value);//undefined
 })//value为上一层返回的结果值(上一次无返回值),则输出的结果为undefined。且本身的then()方法无返回值。

5.异常穿透
只需要在最后指定一个失败的回调即可。

 var p = new Promise((resolve, reject)=>{
       setTimeout(()=>{
            resolve('ok');//执行了所有的回调函数then(),输出结果:111 222 333
            //reject('Err');//直接穿透执行回调函数catch(),输出结果:'Err'。
        },2000);
});
p.then((value)=>{
	//console.log(111);
	throw '出错了';//直接穿透执行回调函数catch(),输出结果:'出错了'。
}).then((value)=>{
	console.log(222);
}).then((value)=>{
	console.log(333);
}).catch((err)=>{
	console.warn(err);
});

6.终止promise的链式操作
答:返回一个pending状态的promise对象

p.then(()=>{
return new Promise(()=>{})//状态未改变不会执行后续的方法
}).then((value)=>{
	console.log(222);
}).then((value)=>{
	console.log(333);
})

八、手写Promise

声明的构造函数

function Promise(executor) {
    // console.log(this);//Promise
    var _this = this;//that self _this
    //初始化这个Promise构造函数的属性
    this.PromiseState = "pending";
    this.PromiseResult = null;
    this.callbacks = [];
    // resolve函数
    function resolve(val) {
        // console.log(this);//Window
        if (_this.PromiseState === "pending") {
            _this.PromiseState = "fulfilled";
            _this.PromiseResult = val;
            // if(_this.callback.onResolved){
            //     _this.callback.onResolved(val);
            // }
            setTimeout(()=>{
                _this.callbacks.forEach((item) => {
                    item.onResolved(val);
                })
            })//异步执行
        }
    }

    // reject函数
    function reject(err) {
        // console.log(this);//Window
        if (_this.PromiseState === "pending") {
            _this.PromiseState = "rejected";
            _this.PromiseResult = err;
            // if(_this.callback.onRejected){
            //     _this.callback.onRejected(err);
            // }
            setTimeout(()=>{
                _this.callbacks.forEach((item) => {
                    item.onRejected(err);
                })
            })//异步执行
        }

    }

    try {
        //同步调用执行器函数
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

then方法

Promise.prototype.then = function (onResolved, onRejected) {
    var _this = this;
    //判断回调函数参数是否传递第二个回调onRejected
    if(typeof onResolved !=='function'){
        onResolved=v=>{
            return v;
        }
    }
    if(typeof onRejected !=='function'){
        onRejected=r=>{
            throw r;
        }
    }

return new Promise((resolve, reject) => {
        function callback(type) {
            try {
                let result = type(_this.PromiseResult);
                //返回promise对象
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v);
                    }, r => {
                        reject(r);
                    })
                } else {
                    //状态为成功(返回非promise对象)
                    resolve(result);
                }
            } catch (e) {
                //throw
                reject(e);
            }
        }

        //同步修改then方法的返回结果
        if (this.PromiseState === "fulfilled") {
            setTimeout(()=>{
                callback(onResolved);
            })//异步执行
        }

        if (this.PromiseState === "rejected") {
            setTimeout(()=>{
                callback(onRejected);
            })//异步执行
        }

        //解决异步任务状态为pending,如何执行后续代码的问题
        if (this.PromiseState === "pending") {
            //保存回调函数
            this.callbacks.push({
                onResolved: function () {
                    // console.log('success');
                    callback(onResolved);
                },
                onRejected: function () {
                    // console.log('error');
                    callback(onRejected);
                }
            })
        }
    })
}

catch方法

Promise.prototype.catch=function(onRejected){
    return this.then(undefined,onRejected);
}

resolve方法

Promise.resolve=function(value){
    return new Promise((resolve, reject) => {
        if(value instanceof Promise){
            value.then((v)=>{
                resolve(v);
            },(r)=>{
                reject(v);
            })
        }else{
            resolve(value);
        }
    })
}

reject方法:永远返回一个失败的promise对象

Promise.reject=function(value){
    return new Promise((resolve, reject) => {
            reject(value);
    })
}

all方法

Promise.all=function(promises){
//返回结果为promise对象
return new Promise((resolve, reject) => {
    let count=0;
    let arr=[];
    for(let i=0;i<promises.length;i++){
        promises[i].then(v=>{
            //状态为成功
            //每个promise对象都成功才成功
            count++;
            //结果放到arr中
            // arr.push(v);//顺序可能打乱
            arr[i]=v;
            if(count === promises.length){
                resolve(arr);
            }
        },r=>{
            //状态为失败
            reject(r);
        })
    }
})
}

race方法

Promise.race=function(promises){
    return new Promise((resolve, reject) => {
        for(let i=0;i<promises.length;i++){
            promises[i].then((v)=>{
                resolve(v);
            },(r)=>{
                reject(r);
            })
        }
    })
}

九、async和await

async函数:

  • 函数的返回结果为promise对象
  • promise对象的结果由async函数执行的返回值决定
        async function main() {
            //1.返回一个非promise对象
            // return 521;//main函数的返回结果为成功的promise对象
            //2.返回一个promise对象
            // return new Promise((resolve, reject) => {
            //     resolve();
            // })
            // return new Promise((resolve, reject) => {
            //     reject();
            // })
            //3.抛出错误
            throw '出错啦';
        }

        let result = main();
        console.log(result);

await函数:

  • await右侧的表达式一般为promise对象,但也可以是其他值
  • 右侧的表达式为promise对象,await 返回结果是promise对象成功的值
  • 右侧的表达式为其他类型值,await 返回结果直接就是该值
  • await必须出现在async中,但是async函数中可以没有await
  • 如果await的promise失败了,就会抛出异常,使用try…catch捕获处理
        async function main() {
            let p = new Promise((resolve, reject) => {
                resolve('ok');
                // reject('err');
            })
            //1.右侧为promise对象
            // let result = await p;
            //2.右侧为其他类型的数据
            // let result = await 20;
            //3.如果promise是失败的状态
            try {
                let result = await p;
                console.log(result);
            } catch (e) {
                console.log(e);
            }
        }
        main();

async和await的结合:

        async function main() {
            // let res = await new Promise((resolve, reject) => {
            //     resolve('521');
            // })
            let res = await 'ok';
            console.log(res);
        }
        main();
  • 发送Ajax请求:
        function sendajax(url) {
            return new Promise((resolve, reject) => {
                var 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.responseText);
                        } else {
                            reject(xhr.status);
                        }
                    }
                }
            })
        }
        var btn = document.querySelector("button");
        btn.addEventListener('click', async function () {
            let duanzi = await sendajax('https://api.apiopen.top/getJoke');
            console.log(duanzi);
        })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值