Promise从入门到精通,小白必看

386 阅读3分钟

实例对象、函数对象、回调等相关知识参考:这个

Promise简介

  1. Promise是一门新的技术(ES6规范),是JS中进行异步编程的新解决方案(旧方案是单纯使用回调函数)。
  2. 从语法上看:Promise是一个构造函数(自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法)。
  3. 从功能上来说: Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值。
  4. ==异步编程: ①fs 文件操作 ②数据库操作 ③Ajax ④setInterval==
  5. Promise指定回调函数的方式更加灵活: 旧的: 必须在启动异步任务前指定 promise: 启动异步任务=> 返回promie对象=> 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)
  6. Promise支持链式调用, 可以解决回调地狱问题(回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件)
<script>
	//回调地狱
	doSomething(function(result){
		doSomethingElse(result,function(newResult){
			doThirdThing(newResult,function(finalResult){
				console.log('Gotthefinalresult:'+finalResult)
			},failureCallback)
		},failureCallback)
	},failureCallback)
	//使用promise的链式调用解决回调地狱
	doSomething().then(function(result){
		return doSomethingElse(result)
	})
	.then(function(newResult){
		return doThirdThing(newResult)
	})
	.then(function(finalResult){
		console.log('Gotthefinalresult:'+finalResult)
	})
	.catch(failureCallback)
	// async/await:回调地狱的终极解决方案
	asyncfunctionrequest(){
		try{const result=awaitdoSomething()
			const newResult=awaitdoSomethingElse(result)
			constfinalResult=awaitdoThirdThing(newResult)
			console.log('Gotthefinalresult:'+finalResult)
		}catch(error){
			failureCallback(error)
		}
	}
</script>

Promise的基本流程

  1. Promise封装一个异步的操作,在成功时调用resolve并把结果传给resolve函数,失败时调用reject并把失败的原因或错误传给reject函数。
  2. 然后在then函数里处理成功或失败的结果。成功(结果数据一般称为value)则调用第一个回调函数里的代码,失败(结果数据一般称为reason)则调用第二个回调函数里的代码。 在这里插入图片描述

Promise的基本使用

对AJAX操作封装

//创建 Promise
const p = new Promise((resolve, reject) => {
    //1.创建对象
    const xhr = new XMLHttpRequest();
    //2. 初始化
    xhr.open('GET', 'https://api.apiopen.top/getJoke');
    //3. 发送
    xhr.send();
    //4. 处理响应结果
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
            //判断响应状态码 2xx   
            if(xhr.status >= 200 && xhr.status < 300){
                //控制台输出响应体
                resolve(xhr.response);
            }else{
                //控制台输出响应状态码
                reject(xhr.status);
            }
        }
    }
});
//调用then方法
p.then(value=>{
    console.log(value);
}, reason=>{
    console.warn(reason);
});

对setInterval操作封装

<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;
        }
        //点击按钮,  1s 后显示是否中奖(30%概率中奖)
        const btn = document.querySelector('#btn');
        btn.addEventListener('click', function(){
            //定时器
            // setTimeout(() => {
            //     //获取从1 - 100的一个随机数
            //     let n = rand(1, 100);
            //     if(n <= 30){
            //         alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券');
            //     }else{
            //         alert('再接再厉');
            //     }
            // }, 1000);

            //Promise 形式实现
            //1)创建promise对象(pending状态),指定执行器函数
            const p = new Promise((resolve, reject) => {
            	//2)在执行器函数中启动异步任务
                setTimeout(() => {
                    //获取从1 - 100的一个随机数
                    let n = rand(1, 100);
                    if(n <= 30){//3.1)如果成功了,调用resolve(),指定成功的value,变为resolved状态,将 promise 对象的状态设置为 『成功』
                        resolve(n); 
                    }else{//3.2)如果失败了,调用reject(),指定失败的reason,变为rejected状态,将 promise 对象的状态设置为 『失败』
                        reject(n); 
                    }
                }, 1000);
            });

            console.log(p);
            //调用 then 方法
            p.then((value) => {//成功的回调函数onResolved,得到成功的vlaue
                alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券, 您的中奖数字为 ' + value);
            }, (reason) => {//失败的回调函数onRejected,得到失败的reason
                alert('再接再厉, 您的号码为 ' + reason);
            });
        });
    </script>
</body>
</html>

Promise的API

1.Promise 构造函数:Promise(executor) {}

  • executor 函数:同步执行 (resolve, reject) => {}
  • resolve 函数:内部定义成功时调用的函数 resove(value)
  • reject 函数:内部定义失败时调用的函数 reject(reason)
  • 说明:executor 是执行器,会在 Promise 内部立即同步回调,异步操作 resolve/reject 就在 executor中

2. Promise.prototype.then 方法:p.then(onResolved, onRejected)

  • onResolved 函数:成功的回调函数 (value) => {}
  • onRejected 函数:失败的回调函数 (reason) => {}
  • 说明:指定两个回调(成功+失败):用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调,返回一个新的promise 对象

3. Promise.prototype.catch方法: (onRejected) => {}

  • onRejected函数: 失败的回调函数(reason) => {}
  • 说明: then()的语法糖, 相当于: then(undefined, onRejected)
new Promise((resolve, reject) => { // excutor执行器函数
 setTimeout(() => {
   if(...) {
     resolve('成功的数据') // resolve()函数
   } else { 
     reject('失败的数据') //reject()函数
    }
  }, 1000)
	}).then(
	 value => { // onResolved()函数
	  console.log(value) // 成功的数据
	}).catch(
	 reason => { // onRejected()函数
	  console.log(reason) // 失败的数据
	}
)

4. Promise.resolve方法: (value) => {}

value: 成功的数据或promise对象说明: 返回一个成功/失败的promise对象

<script>
    //如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
    let p1 = Promise.resolve(521);
    console.log(p1);
    //如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
    let p2 = Promise.resolve(new Promise((resolve, reject) => {
        // resolve('OK');//成功
        reject('Error');//失败
    }));
    console.log(p2);
    p2.catch(reason => {//失败时的处理
        console.log(reason);
    })
</script>

5.Promise.reject方法: (reason) => {}

reason: 失败的原因说明: 返回一个失败的promise对象

<script>
    // let p = Promise.reject(521);
    // let p2 = Promise.reject('iloveyou');
    let p3 = Promise.reject(new Promise((resolve, reject) => {
        resolve('OK');
    }));
    console.log(p3);
</script>

在这里插入图片描述 Promise.resolve()/Promise.reject() 方法就是一个语法糖,用来快速得到Promise对象。

//产生一个成功值为1的promise对象
new Promise((resolve, reject) => {
 resolve(1)
})
//相当于
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)

p1.then(value => {console.log(value)}) // 1
p2.then(value => {console.log(value)}) // 2
p3.catch(reason => {console.log(reason)}) // 3

6.Promise.all方法: (promises) => {}

promises: 包含n个promise的数组说明: 返回一个新的promise, 只有所有promise都成功才成功,结果是成功的结果组成的数组;只要有一个失败了就直接失败,结果是失败那个对象的结果。

let p1 = new Promise((resolve, reject) => {
  resolve('OK');
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Ohhhhh');

const result = Promise.all([p1, p2, p3]);
console.log(result);

7.Promise.race方法: (promises) => {}

promises: 包含n个promise的数组说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态。

<script>
    let p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('OK');
        }, 1000);
    })
    let p2 = Promise.resolve('Success');
    let p3 = Promise.resolve('Oh Yeah');

    //调用
    const result = Promise.race([p1, p2, p3]);

    console.log(result);
</script>

在这里插入图片描述

在这里插入图片描述