理解Promise

一、Promise是什么?

理解

什么是 Promise ?

  • Promise 就是一个对象,用来表示并传递异步操作的最终结果
  • Promise 最主要的交互方式:将回调函数传入 then 方法来获得最终结果或出错原因
  • Promise 代码书写上的表现:以“链式调用”代替回调函数层层嵌套(回调地狱)

1. 抽象表达

  1. Promise是一门新的技术(ES6规范)

  2. Promise是JS中进行异步编程的新解决方案

  • Promise就是为解决“回调地狱”而生的

      备注:旧的方案是单纯使用回调函数

2. 具体表达

  1. 从语法上来说:Promise是一个构造函数
  2. 从功能上来说:Promise对象用来封装一个异步操作并可以获取其成功或失败的结果值。
  • Promise 对象用来进行延迟(deferred) 和异步(asynchronous ) 计算

二、Promise对象的状态改变

Promise的状态指的是实例对象中的一个属性PromiseState,它的值有三个:

  1. pending:未决定的
  2. resolve/fulfilled:成功
  3. rejected:失败

Promise的状态改变只有下面的三种情况:

  1. pending变为resolved
  2. pending变为rejected
  3. 抛出异常:如果当前为pending就会变为rejected

说明:只有这3种,且一个Promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason

简单使用:

 var $ = {
      //基于回掉函数机制
        get({url,success,error}){
            // 异步交互  
            // 1.new xhr实例
            let xhr = new XMLHttpRequest();
            // 2.设置请求行
            xhr.open('get', url,);
            // 3.设置请求头
            xhr.setRequestHeader('content-type', 'application/json');
            // 设置请求返回格式
            // xhr.responseType = 'json';
            // 4.发送请求
            xhr.send();
            // 监听
            xhr.onreadystatechange = function() {
                if(this.readyState == 4 && this.status==200){
                      success(this.response)//回调函数
                }else{
                  error(this)
                }
            }
        }
    }
$.get({
    url:'http://47.100.226.238:8888/index/category/findAll',
    success:function(res){
        console.log(res);
        console.log(JSON.parse(res));//转为json对象
    },
    error:function(res){
      console.log(res)
    }
})

var axios = {
        //基于承诺对象Promise机制
        get(url){
            return new Promise(function(resolve,reject){
                //1.new xhr实例
                let xhr = new XMLHttpRequest();
                //2.设置请求行
                xhr.open('get',url)
                //3.设置请求头
                xhr.setRequestHeader("Content-Type", "application/json")
                // 设置请求返回格式  最简单方式
                xhr.responseType = 'json';
                //4.发送请求
                xhr.send()
                //5.监听
                xhr.onreadystatechange = function(){
                    if(this.readyState == 4){
                        if(this.status == 200){
                            resolve(this.response)
                        }else {
                            reject(this.response)
                        }
                    }
                }
            })
        }
    }

    //使用
    let t=axios.get('http://47.100.226.238:8888/index/carousel/findAll');// t是承诺对象(要使用.then,里面还可能用回调函数)
    t.then((res)=>{
      // then方法是定义在原型对象Promise.prototype上的。
      // 它的作用是为 Promise 实例添加状态改变时的回调函数。
      // then方法的第一个参数是resolve,第二个是rejected
        console.log(res);
    })
    .catch((err)=>{
        console.log(err);
    })

三、为什么要使用Promise?

1. 指定回调函数的方式更加灵活

  1. 旧的:必须在启动异步任务前指定
  2. promise:启动异步任务=> 返回promise对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定一个或多个)

2. 支持链式调用(就是可以加多个.then()),可以解决回调地狱问题

  •  then方法是定义在原型对象Promise.prototype上的。
  • 它的作用是为 Promise 实例添加状态改变时的回调函数。
  •  then方法的第一个参数是resolve,第二个是rejected

什么是回调地狱?

回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件

回调地狱的缺点? 不便于阅读 / 不便于异常处理
解决方案? promise链式调用
终极解决方案? async/await

JS 异步编程进化史:callback -> promise -> generator -> async + await
 

回调地狱
$.ajax({
    url:"查询用户",
    success:function(res){
        console.log(res)
        // 将数据渲染到页面上
        $.ajax({
            url: "查询到课程",
            success:function(res){
                // 获取到了课程内容的数据,渲染到页面上
                $.ajax({})
            }
        })
    }
})

promise 处理回调地狱
new Promise(function(resolve, reject){
    $.ajax({
        url:"查询用户",
        success:function(res){
                resolve(res)
        },
        error:function(err){
                reject(err)
        }   
    })
}).then(res=>{
    console.log(res)
        return new Promise(function(resolve,rejeect){
            $.ajax({
                    url: "查询到课程",
                    success:function(res1){
                            // 获取到了文章详细内容的数据,渲染到页面上
                            resolve(res1)   
                    },
                    error:function(err){
                        reject(err)
                    }   
            })
        })
}).then(res=>{
    console.log(res)
    return new Promise(function(resolve,rejeect){
            $.ajax({
                    url: "查询到分数",
                    success:function(res1){
                            // 获取到了文章详细内容的数据,渲染到页面上
                            resolve(res1)   
                    },
                    error:function(err){
                        reject(err)
                    }   
            })
        })
}).then(res=>{
    console.log(res)
})

封装一下 Promise
function get(url) {
    return new Promise((resolve, reject) => {
        $.ajax({
            url: url,
            success: function (data) {
                resolve(data);
            },
            error: function (err) {
                reject(err)
            }
        })
    });
}

//调用封装后的方法 
get("查询用户")
    .then((data) => {
        console.log("用户查询成功~~~:", data)
        return get("查询到课程);
    })
    .then((data) => {
        console.log("课程查询成功~~~:", data)
        return get("查询到分数);
    })
    .then((data) => {
        console.log("课程成绩查询成功~~~:", data)
    }).catch((err) => {
        console.log("出现异常", err)
    });


async function foo() {
  try {
    const result = await doSomething();
    const newResult = await doSomethingElse(result);
    const finalResult = await doThirdThing(newResult);
    console.log(`Got the final result: ${finalResult}`);
  } catch(error) {
    failureCallback(error);
  }
}

Promise.all

可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。

et p1 = new Promise((resolve, reject) => {
  resolve('成功了')
})

let p2 = new Promise((resolve, reject) => {
  resolve('success')
})

let p3 = Promse.reject('失败')

Promise.all([p1, p2]).then((result) => {
  console.log(result)               //['成功了', 'success']
}).catch((error) => {
  console.log(error)
})

Promise.all()执行顺序和返回顺序 (返回的是对象)

// 方法promiseA,返回一个Promise对象
function promiseA() {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log('A')
			resolve('A')
		}, 3000)
	})
}
// 方法promiseB,返回一个Promise对象
function promiseB() {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log('B')
			resolve('B')
		}, 1000)
	})
}
// 按照A, B的顺序添加到promise数组中
Promise.all([promiseA(), promiseB()]).then(resolve => {
	console.log(resolve)
})
// 输出情况
B
A 
Array [ "A", "B" ]

console.log()可以看出的确是按照谁执行的快谁先打印结果, 但是最终返回的结果仍然是按照promise的添加顺序返回的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值