Js es6 Promise理解和使用

js中的promise是一个异步编程的解决方案,语法层面上他是一个构造函数,名字为Promise()。

它的作用就是将一个任务task封装为一个Promise类的实例对象,这个对象会将任务自动运行并得到任务结果,而且在得到结果的过程中并不会影响到其他任务的进行。由此实现多个任务的并发进行。

实现异步的过程被隐藏在Promise类的实现过程中,我们只需要将任务交给Promise,Promise给我们一个instance,之后通过instance去拿任务结果就可以了。我们可以创建多个Promise类的实例instance。

一:Promise构造函数参数和基本使用介绍

1: Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。resolve和reject是两个函数,由JavaScript引擎提供,不用自己部署。

//resolve, reject名称不能修改
const promise = new Promise(function(resolve, reject) {
    // ...some code
    if ( /*异步操作成功,执行resolve方法,目的一般是将某些结果返回出去*/ ) {
        resolve(value);
    } else {
        /*异步操作失败,执行reject方法,目的一般也是将某些结果返回出去*/
        reject(error);
    }
});

2: Promise实例对象的then()方法

Promise 实例生成以后,可以用then方法分别指定resolved状态和rejected 状态的回调函数。也就是对返回的任务结果进行处理。

promise.then(resolved = function(value) {
        // success,对返回的结果value进行处理
    },
    rejected = function(error) {
        //failure,直接把错误类型报给用户
});

3:异步加载图片的例子

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ajax实操</title>
</head>
 
<body>
    <div id="box"></div>
    <script>

        //resolve, reject名称不能修改
		const promise = new Promise(function(resolve, reject) {
		    // ...some code
		    if ( /*异步操作成功,执行resolve方法,目的一般是将某些结果返回出去*/ ) {
		        resolve(value);
		    } else {
		        /*异步操作失败,执行reject方法,目的一般也是将某些结果返回出去*/
		        reject(error);
		    }
		});

        let box = document.getElementById('box');
 
        function GETJSON(url) {
            /*************************************************************/
            function ajaxTask(resolve, reject) {
                const handler = function() {
                    if (this.readystate !== 4) {
                        return;
                    }
                    if (this.status === 200) {
                        resolve(this.response);
                    } else {
                        reject(new Error(this.statusText));
                    }
                };
                const client = new XMLHttpRequest();
                client.open("GET", url);
                client.onreadystatechange = handler;
                client.responseType = "json";
                client.setRequestHeader("Access-Control-Allow-Origin", "*");
                client.send();
            }
            /*************************************************************/
            return new Promise(ajaxTask);
        };
        /*************************************************************/
        promise = GETJSON("https://www.hupu.com/home/v1/news?pageNo=4&pageSize=50");//出现ajax无法跨域的问题,目前还不会解决
 
        promise.then(
            function(data) {
                console.log(data);;
            },
            function(error) {
                box.innerHTML = '加载失败';
                console.log(error);
            }
        )
    </script>
</body>
</html>

4:有顺序的执行某些请求,我们把每个请求(promise形式)串起来搞成链式调用

//验证
function getAuth(){
    return new Promise((res,rej)=>{
        //关键代码
    })
}
//用户信息
function getUsers(){
    return new Promise((res,rej)=>{
        //关键代码
    })
}
//页面信息
function getPageInfo(){
    return new Promise((res,rej)=>{
        //关键代码
    })
}
//请求顺序:先验证 => 再拿用户 => 再拿页面信息
getAuth().then(res => {
    if(res.success){
        //验证通过,请求用户信息
        return getUsers();
    }else{
        return Promise.reject();
    }
}).then(res => {
    if(res.success){
        //成功获取用户信息,请求页面信息
        return getPageInfo();
    }else{
        return Promise.reject();
    }
}).then(res => {
    if(res.success){
        //成功获取页面信息,反射数据到视图上
 
        //over request
    }
})

5:同时发送多个并行的请求,失败的记录,成功的执行相应的逻辑

function requestMain(urls,successfn,failurefn){
    //图片url资源路径
    let urls = [
     'https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=2363246672,1942618513&fm=58',                      
     'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=4138785756047,2461366902&fm=58',           
     'https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=378711121878161,3674972757&fm=58',
     'https://ss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2412121295993728,2346220807&fm=58',
    ];
    let errorArr = [];//记录错误的信息
    //构建promise的函数
    function generatePromise(url){
        return new Promise((res,rej)=>{
            //
        })
    }
    urls.reduce((promise,url,index)=>{
        promise.then(res => {
            //请求成功执行的回调
            successfn(res);
        }).catch(err=>{
            //失败时,记录失败信息
            errorArr.push(err);
        }).then(()=>{
            if(index === urls.length-1 && errorArr.length > 1){
                //全部请求完,并且错误数组不为空时执行回调
                failurefn(errorArr);
            }else{
                promise = generatePromise(url)
            }
        })
    },
    Promise.reject(false))
}

6:避免陷入回调地狱

在这里插入图片描述
具体使用:
在这里插入图片描述
在这里插入图片描述
(1) 首先定义三个url的地址;获取第一个url,通过getData(),它return new Promise也就是return一个promise的class的实例。
(2) getData(url1).then 这个then就是new Promise里面的方法,.then(data1 => {console.log(data1) return getData(url2)})。data1就是我们通过url1获取的数据,然后打印出来,这个地方直接return getData(url2),直接return,然后就直接可以再后面.then,我们看data2,然后return getData(url3),.then,最后.catch,它是一个防错处理,万一那一层遇到问题,就会触发error这个回调函数,就会触发catch。
(3) 写法上.then .then .then…… .then都是单层的,是一个管道形式,就是一节对应一节,一节对应一节,它不是一个嵌套形式,不像回调地狱那样,一层一层嵌套。
(4) promise里面还是一个callback的形式,但是它把callback的形式变成了非嵌套的形式,变成了管道式的串联的形式,这就是一个进步,一串一串的形式,串联着走,永远都是一层,这就是promise的一个形式。

二:理论理解

promise是浏览器引擎自带的(但不是所有浏览器都支持promise)
在这里插入图片描述
promise的参数是一个函数且必须有这个函数,否则报错,姑且命名为A函数;

let p = new Promise()
console.log(p); // TypeError: Promise resolver undefined is not a function

A函数里有两个参数,这两个参数也是函数。res和rej这两个参数都是函数,名字随意。
res是成功时的回调
rej是失败时的回调

在这里插入图片描述
new Promise函数是同步函数,并且是立即执行的

promise共有三种状态,pending,fulfilled,rejected

  • 状态只能从pending变为fulfilled状态,成功状态。
  • 或者从pending变为rejected状态,失败状态。

例如:pending转变到fulfilled,状态就确定了,只能是fulfilled状态;如果想转成rejected状态,是不能转的。

当promise刚new出来时,是pending状态:
在这里插入图片描述
promise函数对象有三个属性,如上图展示的,[[Prototype]]其实就是是__ proto__;其他两个属性如下:

PromiseState:就是promise的现在状态:

当你调用res函数,状态立马变为fulfilled(成功状态)
在这里插入图片描述
当你调用rej函数,状态立马变为rejected(失败状态)
在这里插入图片描述
如果两个状态都存在,以谁先调用为准:
在这里插入图片描述

PromiseResult :res或rej返回的结果

PromiseResult就是res或rej执行后的返回的结果,是返给then的。
在这里插入图片描述
当你new 一个promise时,就已经开始自动执行函数。promise是同步的,但then是异步的,要注意区分

promise实例原型上的then函数:

在这里插入图片描述
res函数和rej函数返回的数据,谁来接收的,用then函数

then函数里的参数是两个异步回调函数,是异步的哈,第一个参数函数用于接收res返回来的数据,第二个参数函数用于接收rej返回的数据。

then的第一个参数函数里的形参用来接收res返回的数据:
在这里插入图片描述
then的第二个参数函数里的形参用来接收rej返回的数据:
在这里插入图片描述

其实then里面的函数就是res和rej
在这里插入图片描述
如果new promise中没有写res或rej 则then里的函数不会执行:

let p = new Promise((res,rej)=>{
	
})
p.then(val=>{
	console.log(11); // 11不输出
})

then的返回值:

(1) 如果(父级)上一个then返回的是数据或undefined,则(子级)下个then的状态为成功状态,并将父级返回值返回到子级then的参数里面:

let p = new Promise((res,rej)=>{
	res(11)
})
// 父级then
let p1 = p.then(val=>{
	console.log(val); // 11
	// 默认是return undefined
})
// 子级then ,then中的参数是上一个then返回的值,
p1.then(value=>{
	console.log(value); // undefined
})

在这里插入图片描述

(2) 如果父级then返回的是一个数据:

let p = new Promise((res,rej)=>{
	res(11)
})

let p1 = p.then(val=>{
	console.log(val);
	return {name:'wyy'}
})

p1.then(value=>{
	console.log(value);
})

在这里插入图片描述
(3) 如果父级then抛出的是一个错误,则父级then的状态为失败状态,并将失败状态的值返回给子级then:

通过throw主动抛出错误或者代码出现错误,则promise的状态为rejected,值为throw的值;或者代码出错也为rejected状态,例如输出一个不存在的a;console.log(a)。

第二个then的promise实例状态是根据p.then的返回值决定的

在这里插入图片描述
在这里插入图片描述
如果没有return,则默认为undefined,即是fulfilled状态。

catch

catch是处理rej函数的。当返回错误时调用catch:
在这里插入图片描述
当new promise出现rej(), throw, 语法错误以上三种形式式,就会调用catch函数。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值