Promise的使用和总结

文章书写原则

  • 最小知识原则
    本文章中的函数用es5函数的形式,不涉及箭头函数

基本使用

var promise =  new Promise(function(resolve,reject){
    //用setTimeout延时1s模拟异步调用,比如网络请求
    setTimeout(function(){
        //用一个随机数 0或1 表示网络请求的成功或失败
        var status = Math.round(Math.random())
        if(status){//status===1 请求成功
        	var data = '请求成功咯' //网络请求拿到的数据
            resolve(data);
        }else{    //status === 0 请求失败
        	var err = '请求失败咯' // 错误信息
            reject(err);
        }
    },1000)
})

promise.then(
    function(res){ //成功的回调
        console.log('成功的回调被调用')
        console.log(res)
    },
    function(err){  // 失败的回调
        console.log('失败的回调被调用')
        console.log(err)
    }
)

new Promise()返回一个promise实例,Promise构造函数接收一个函数作为参数,这个函数也接收两个回调函数作为参数,分别是

  • resolve()
    异步请求成功时调用,参数是要返回的数据
  • reject()
    异步请求错误时调用,参数是要返回的数据

promise实例有一个then()方法,方法也接收两个回调函数作为参数,分别是

  • 成功的回调,如示例例代码中写的。函数的参数是resolve()传递的数据
function(res){ 
   console.log('成功的回调调用')
   console.log(res)
},
  • 失败的回调,如示例例代码中写的。函数的参数是reject()传递的数据
function(err){ 
   console.log('失败的回调被调用')
   console.log(err)
}

可以理解new Promise(func)func函数的两个参数函数就是promise.then(func1,func2)then函数的两个回调函数

案例:微信小程序api实现Promise化

微信小程序原生的网络请求api

wx.request({
  url: 'test.php', //仅为示例,并非真实的接口地址
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  },
  success (res) {
    console.log(res.data)
  }
})

实现promise化的网络请求api

//promise化的方法
function promisify(func){
	return function(obj){
		return new Promise(function(resolve,reject){
			//根据微信api指定的参数
			func({
			...obj,
			success: resolve,
			fail: reject
			})
		})
	}
}

const requst = promisify(wx.request)
//调用promise化的网络请求api
const result = request({
  url: 'test.php', //仅为示例,并非真实的接口地址
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  }
})
//可以用promise的链式调用了,可以一直then下去,最后可以catch捕获一下可能发生的网络请求失败(相当于promise状态变为rejected)
result.then(function(res){
	console.log('请求成功了,响应的内容:',res)
}).catch(err){
	console.log('请求发生错误了,错误:',err)
}

Promose的定义

MDN中的描述:

Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象

如上的request的promise化,实际上是代理了它的请求状态,这时request的请求状态是未知的,可能请求失败也可能请求成功。
所以我为request的成功和失败状态分别绑定了resolve函数和reject函数

// ......
func({
	...obj,
	success: resolve,
	fail: reject
})
// ......

MDN的描述中所指的处理方法handlers就是function(resolve,reject){}

// ......
return new Promise(function(resolve,reject){
	func({
	...obj,
	success: resolve,
	fail: reject
	})
})
// ......

经过promise化的api就可以像同步代码那样有返回值,如下返回了一个promise对象result

const result = request({
  url: 'test.php', //仅为示例,并非真实的接口地址
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  }
})

这个promise对象它以自己状态代表着未来出现的结果(成功或失败)。

Promise的状态

Promise有三种状态,分别是

  • pending
    也就是promise的初始化状态,代表着未来出现的结果还未确定
  • fulfilled
    出现的结果确定,代表操作成功
  • rejected
    出现的结果确定,代表操作失败

promise的状态改变是一个不可逆的过程,只能从panding--> fulfilled/rejected,而不能逆过来。

  • panding --> fulfilled
    Promise.resolve()方法被调用时,状态从panding变为fulfilled
  • panding --> rejected
    Promise.reject()方法被调用时,状态从panding变为rejected

如在小程序api中,当请求成功时调用handers中的resolve方法;失败时调用reject方法

// ......
func({
	...obj,
	success: resolve,
	fail: reject
})
// ......

也可以用Promise的静态函数直接得到一个状态已经确定的promise实例。如下

let obj = '可以是任意对象'
let p = Promise.resolve(obj)
console.log(promise)

变量p是一个状态为fulfilled的Promise实例(fulfilled 等同于 resolved
在这里插入图片描述

同理:
在这里插入图片描述

Promise的API和实例方法

  • Promise.all(iterable)
  • Promise.race(iterable)
  • Promise.reject(reason)
    返回一个状态为rejected的promise实例,且实例的值为reason
  • Promise.resolve(value)
    返回一个状态为fulfilled的promise实例,且实例的值为value
  • p.then(onFulfilled, onRejected)
    接收两个回调参数,成功状态的回调和失败状态的回调。失败状态的回调常常省略不写,而用p.catch方法代替
  • p.catch(onRejected)
    接收一个回调参数,状态为rejected时调用。等价于p.then(undefined, onRejected)

参考文章

MDN
微信开发者文档·小程序
Promises

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值