Promise

Promise是什么?

  1. 抽象表单:Promise是JS异步编程的新解决方案(旧的是回调)
  2. 具体表达:

从语法上来说:Promise是一个构造函数
从功能上来说:promise对象是用来封装一个异步操作并可以获取其结果

promise状态改变

  1. 初始为pending
  2. pending变为resolved
  3. pending变为rejected

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

promise的基本流程

在这里插入图片描述

const p = new Promise((resolve,reject)=>{
    if(Date.now() % 2 == 0){
        resolve(1)
      }else{
        reject(0)
      }
}).then(value=>{
    console.log('成功的回调' + value) //1
},reason=>{
    console.log('失败的回调' + reason) //0
})

为什么要用promise

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

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

  1. 支持链式调用,可以解决回调地狱的问题

什么是回调函数?回调函数嵌套调用,外部回调函数的异步执行结果是内部函数执行的条件;
回调地狱的缺点:不便于阅读,不便于异常处理
解决方案:promise链式调用
终极解决方案:async/await

如何使用promise

API

  1. Promise构造函数:Promise(excutor){}
    (1) excutor函数:执行器excutor(resolve,reject)=>{}
    (2) resolve函数:内部定义我们成功时调用的函数 value=>{}
    (3) reject函数:内部定义我们失败时调用的函数 reason=>{}
    说明:excutor会在promise内部立即同步执行,异步操作在执行器中执行
  2. promise.prototype.then 方法:(onResolved,onRejected)=>{}
    (1) onResolved函数:成功的回调函数 (value)=>{}
    (2) onRejected函数:失败的回调函数 (reason)=>{}
    说明:指定用于得到成功value成功回调函数,和得到失败reason的失败回调函数,返回一个新的promise对象;
  3. promise.prototype.catch 方法:(onRejected)=>{}
    onRejected函数:失败的回调函数 (reason)=>{}
    说明:then的语法糖,相当于:then(undefined,onRejected)=>{}
  4. Promise.resolve方法:(value)=>{}
    value:成功的数据或者promise对象
    说明:返回一个成功/失败的promise对象
  5. Promise.reject方法:(reason)=>{}
    reason:失败的原因
    说明:返回一个失败的promise对象
  6. Promise.all方法:(promises)=>{}
    promises:包含n个promise的数组
    说明:返回一个新的promise对象,只有所有的promise都成功才返回成功,否则返回失败;
  7. Promse.race方法:(promises)=>{}
    promises:包含n个promise的数组
    说明:返回一个新的promise对象,第一个完成promise的结果状态就是最终的状态;

Promise的几个关键问题

1.如何改变 promise的状态?
(1) resolve(value):如果当前是 pending就会变为 resolved
(2) reject(reason):如果当前是 pending就会变为 rejected
(3)抛出异常:如果当前是 pending就会变为 rejected
2.一个 promise指定多个成功/失败回调函数,都会调用吗?
当 promise改变为对应状态时都会调用
3. 改变 promise状态和指定回调函数谁先谁后
(1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改状态再指定回调
(2)如何先改状态再指定回调?
①在执行器中直接调用 resolve()/ reject()
②延迟更长时间才调then()
(3)什么时候才能得到数据?
①如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
②如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据
4. promise.then()返回的新 promise的结果状态由什么决定?
(1)简单表达:由then()指定的回调函数执行的结果决定
(2)详细表达
①如果抛出异常,新 promise变为 rejected, reason为抛出的异常
②如果返回的是非 promise的任意值,新 promise变为 resolved,value为返回的值
③如果返回的是另一个新 promIse,此 promIse的结果就会成为新 promise的结果
5. promise如何串连多个操作任务?
(1) promise的then()返回一个新的 promise,可以开成then()的链式调用
(2)通过then的链式调用串连多个同步/异步任务
6. promise异常传透
(1)当使用 promise的then链式调用时,可以在最后指定失败的回调
(2)前面任何操作出了异常,都会传到最后失败的回调中处理
(3) 不写失败回调函数相当于默认 reason=>{throw reason}
7.中断 promise链?
(1)当使用 promIse的then链式调用时,在中间中断,不再调用后面的回调函数
(2)办法:在回调函数中返回一个 pending状态的 promise对象

手写Promise

(function(){
	const PENDING = 'pending'  //初始状态
	const RESOLVED = 'resolved' //成功状态
	const REJECTED = 'rejected' //失败状态
	//Promise构造函数
	function MyPromise(excutor){
		const self = this
		//初始化状态
		self.status = PENDING
		self.data = undefined
		self.callbacks = [] //每个元素的结构: {onResolved(value){}, onRejected(reason){} }
		//resolve方法
		function resolve(value){
			if(self.status !== PENDING){
				return
			}
			//改变状态,保存数据
			self.status = RESOLVED
			self.data = value
			//如果有待执行回调函数,立即异步执行异步回调函数
			if(self.callbacks.length > 0){
				setTimeout(()=>{
					self.callbacks.forEach(item=>{
						item.onResolved(value)
					})
				})
			}
		}
		//reject方法
		function reject(reason){
			if(self.status !== PENDING){
				return
			}
			//改变状态,保存数据
			self.status = REJECTED
			self.data = reason
			//如果有待执行回调函数,立即异步执行异步回调函数
			if(self.callbacks.length > 0){
				setTimeout(()=>{
					self.callbacks.forEach(item=>{
						item.onRejected(reason)
					})
				})
			}
		}
		//立即执行excutor函数
		try{
			excutor(resolve,reject)
		}catch(error){
			reject(error)
		}
	}
	//Promise对象的then方法
	MyPromise.prototype.then = function(onResolved,onRejected){
		onResolved = typeof onResolved === 'function' ?onResolved : value => value,  //不写默认undefined
		//指定默认是失败回调
		onRejected = typeof onRejected === 'function' ?
		  onRejected : reason => {
			throw reason
		  }
		const self = this
		//返回一个新的promise对象
		return new MyPromise((resolve,reject)=>{
			function handle(callback){
				try{
					//回调函数返回的结果
					const result = callback(self.data)
					if(result instanceof MyPromise){
						//返回的数据是Promise
						result.then(resolve,reject)//返回新的promise对象
					}else{
						resolve(result)
					}
				}catch(error){
					reject(error)
				}
			}
			if(self.status === PENDING){
				self.callbacks.push({
					onResolved(value){
						handle(value)
					},
					onRejected(reason){
						handle(reason)
					}
				})
			}else if(self.status === RESOLVED){
				setTimeout(()=>{
					handle(onResolved)
				})
			}else{
				setTimeout(()=>{
					handle(onRejected)
				})
			}
		})
	}
	//Promise对象的catch方法
	MyPromise.prototype.catch = function(onRejected){
		return this.then(undefined, onRejected)
	}
	//Promise的resolve方法
	MyPromise.resolve = function(value){
		return new MyPromise((resolve,reject)=>{
			if(result instanceof MyPromise){
				//返回的数据是Promise
				result.then(resolve,reject)//返回新的promise对象
			}else{
				resolve(result)
			}
		})
	}
	//Promise的reject方法
	MyPromise.reject = function(reason){
		return new MyPromise((resolve,reject)=>{
			reject(reason)
		})
	}
	//Promise的all方法
	MyPromise.all = function(promises){
		const values = new Array(promises.length) //保存成功的数据数据
		let resolvedCount = 0 //成功的数量
		return new MyPromise((resolve,reject)=>{
			//遍历执行promises
			promises.forEach((item,index)=>{
				MyPromise.resolve(item).then(
					value=>{
						reslovedCount++
						values[index] = value
						if(reslovedCount === promises.length){
							resolve(values)
						}
					},
					reason=>{
						reject(reason)
					}
				)
			})
		})
	}
	//Promise的race方法
	MyPromise.race = function(promises){
		return new MyPromise((resolve,reject)=>{
			promises.forEach((item,index)=>{
				MyPromise.resolve(item).then(
					value=>{
						resolve(value)
					},
					reason=>{
						reject(reason)
					}
				)
			})
		})
	}
	window.MyPromise = MyPromise
})()
//使用
var p = new MyPromise((resolve,reject)=>{
		resolve(1)
	})

async与await

  1. async函数
  • 函数的返回值为 promise对象
  • promise对象的结果由 async函数执行的返回值决定
  1. await表达式
  • await右侧的表达式一般为 promise对象,但也可以是其它的值
  • 如果表达式是 promise对象,awat返回的是 promise成功的值
    3.注意await必须写在 async函数中,但 async函数中可以没有 await如果 await的 promise失败了,就会抛出异常,需要通try. catch来捕获处理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值