Promise学习笔记

promise对象用来封装一个异步操作并可以获得其结果

在这之前我们先了解一下回调函数的分类

1.同步回调,立即执行,执行完了才结束,像数组遍历/Promise的excutor函数
const arr = [1,3,5];
arr.forEach(item=>{
	console.log(item)
})
console.log('先回打印1,3,5,才轮到我')
2.异步回调,不会立即执行,会放入回调队列中将来执行例如定时器/ajax/Promise的成功失败状态回调,定时器设置0调用也是异步
setTimeout(()=>{
	console.log('timeout');//异步回调函数会放到队列中,等待同步任务执行完成,再调用
},0)
console.log('我会在timeout之前出现');
3.错误的类型

Error:所有错误的父类型
ReferenceError:引用的变量不存在
TypeError:数据类型不正确的错误
RangError:数据值不在其所允许的范围内
SyntaxError:语法错误

 //   常见的内置错误
 // 1) ReferenceError: 引用的变量不存在
 console.log(a);
 console.log('上面出问题了,你是打印不了我的');   // 没有捕获error,下面的代码不会执行
//Uncaught ReferenceError: a is not defined
 
 
 // 2) TypeError:数据类型不正确的错误
 let obj={}; 
 obj.a();//Uncaught TypeError: obj.a is not a function
 
 
 // 3) RangError:数据值不在其所允许的范围内,一般使用递归跳出条件出错就会报这种错误
 //求斐波拉契数列 1,1,2,3,5,8,13,21....从第三项开始,后一项等于前两项的和
 //也就是第n项=第(n-1)项+第(n-2)项 n>2
 //错误的
 {
 	function fn(num){ 
 		if(num == 1){ 
 			return 1
 		}else{ 
 			return fn(num-1)+fn(num-2)
 		} 
 	} 
 	fn(5)
 	//Uncaught RangeError: Maximum call stack size exceeded
    //at fn (<anonymous>:2:4)
    //at fn (<anonymous>:5:12)
    //at fn (<anonymous>:5:12)
    //at fn (<anonymous>:5:12)
    //at fn (<anonymous>:5:12)
    //at fn (<anonymous>:5:12)
    //at fn (<anonymous>:5:12)
    //at fn (<anonymous>:5:12)
    //at fn (<anonymous>:5:12)
    //at fn (<anonymous>:5:12)
 }
 //正确的
  {
 	function fn(num){ 
 		if(num == 1||num == 2){ //第一项和第二项都为1
 			return 1
 		}else{ 
 			return fn(num-1)+fn(num-2)
 		} 
 	} 
 	fn(5)//5
 }
 // 4) SyntaxError: 语法错误
let obj={
	nameage:1;//对象内不能使用分号
};
//Uncaught SyntaxError: Unexpected token ';'

4.错误处理 捕获错误:try…catch
错误对象

message属性: 错误相关信息
stack属性: 函数调用栈记录信息

//捕获错误
try{
	let b;
	console.log(b.xxx);
}catch(error){
	console.log(error.message);//错误相关信
	console.log(error.stack);//函数调用栈记录信息
}
//Cannot read property 'xxx' of undefined
//TypeError: Cannot read property 'xxx' of undefined
抛出错误
//抛出错误
function sth(){
	if(Date.now() % 2 === 1){
		cosnole.log('当前时间为奇数执行')
	}else{
		throw new Error('当前时间为偶数,无法执行,抛出错误')
	}
}
try{
	sth();
}catch(error){
console.log(error.message)
}

Promise基本使用

Promise是JS中进行异步编程的新解决方案(旧的是纯回调)
语法上:Promise是一个构造函数
功能上:promise对象用来封装一个异步操作并可以获取其结果

//1.创建一个新的promise对象
const p = new Promise((resolve,reject)=>{//执行器函数,同步回调
	console.log('执行excutor')
	//2.执行异步操作任务
	setTimeout(()=>{
		const time = Date.now()//获取当前时间判断奇偶性,设置状态
		if(time % 2 == 0 ){
			resolve(`成功的状态,time=${time}`)
		}else{
			reject(`失败的状态,time=${time}`)
		}
	},1000)
})
console.log('我会在上面执行excutor后打印');
console.log(p);//不确定状态可以直接打印实例对象查看,
p.then(
    value => { // 接收得到成功的value数据    onResolved
        console.log('成功的回调', value)
    },
    reason => {// 接收得到失败的reason数据  onRejected
        console.log('失败的回调', reason)
    }
)
//执行excutor
//我会在上面执行excutor后打印
//Promise {<pending>}
//Promise {<pending>}
//失败的回调 失败的状态,time=1628302893857

使用Promise的优点

1.指定回调函数的方式更加灵活,简单,必须在启动异步任务之前指定promise,启动异步任务=>返回 promise对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定)
2.支持链式调用,可以解决回调地狱问题
回调地狱中函数层层嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件,不便于阅读,不便于异常处理
使用promise链式调用可以解决,终极解决方案使用async/await

//回调地狱
doSomething(function(result) {
	doSomethingElse(result, function(newResult) {
  		doThirdThing(newResult, function(finalResult) {
    		console.log('Got the final result: ' + finalResult)
  		}, failureCallback)
	}, failureCallback)
}, failureCallback)
//使用promise的链式调用解决回调地狱
doSomething()
  .then(function (result) {
      return doSomethingElse(result)
  })
  .then(function (newResult) {
      return doThirdThing(newResult)
  })
  .then(function (finalResult) {
      console.log('Got the final result: ' + finalResult)
  })
  .catch(failureCallback)  // 任何一个发生异常都传入这里
//async/await: 回调地狱的终极解决方案
async function request() {
  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的状态改变

当我们通过new Promise获得一个promise实例对象时,它的状态为pendding状态,
通过我们设置或者异步的结果会改变它的状态
pendding(等待),resolved(成功),rejected(失败)
它的状态细分就这三种,一般只记成功失败,它的状态只能改变一次,无论成功还是失败,都会有一个结果数据,一旦确定后面不会改变

Promise的API
  1. Promise构造函数: Promise (excutor) {} excutor函数: 同步执行 (resolve, reject) => {} resolve函数: 内部定义成功时我们调用的函数 value => {} reject函数: 内部定义失败时我们调用的函数 reason => {} 说明: excutor会在Promise内部立即同步回调,异步操作在执行器中执行
  2. Promise.prototype.then方法: (onResolved, onRejected) => {} onResolved函数: 成功的回调函数 (value) => {} 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. Promise.race方法: (promises) => {} promises: 包含n个promise的数组 说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态
 new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("成功的数据");
          reject("失败的数据");
        }, 1000);
      })
        .then((value) => {
          console.log("onResolved()1", value);
        })
        .catch((reason) => {
          console.log("onRejected()1", reason);
        }); // 产生一个成功值为1的promise对象
        const p1 = new Promise((resolve, reject) => {    setTimeout(() => {        resolve(1)    }, 100);})
        const p2 = Promise.resolve(2)
        const p3 = Promise.reject(3)
        // p1.then(value => { console.log(value) })
        // p2.then(value => { console.log(value) })
        // p3.catch(reason => { console.log(reason) })
        // const pAll = Promise.all([p1, p2, p3])
        const pAll = Promise.all([p1, p2])
        pAll.then(
        values =>{  
        	console.log('all onResolved()', values)
        },
        reason => {        
        	console.log('all onRejected()', reason)    	
        })
        const pRace = Promise.race([p1, p2, p3])
        pRace.then(    
        value => {        
       		console.log('race onResolved()', value)    
        },    
        reason => {        
        	console.log('race onRejected()', reason)    
        })
如何改变promise的状态?

(1)resolve(value): 如果当前是pending就会变为resolved
(2)reject(reason): 如果当前是pending就会变为rejected
(3)抛出异常: 如果当前是pending就会变为rejected

let p = new Promise((resolve, reject) => {    
resolve('Promise状态会被标记为resolved')  
// reject('Promise状态会被标记为rejected')   
throw new Error('Promise状态会被标记为rejected')});
一个promise指定多个成功/失败回调函数, 都会调用吗?

当promise改变为对应状态时都会调用

let p = new Promise((resolve, reject) => {    
throw 3;});// 两个then都会进行
p.then(    
value => {        
	console.log('value1', value)     
},    
	reason => {        
console.log('reason1', reason)// reason1 3                                                                            })
p.then(    
value => {        
  	console.log('value2', value)    
},    
reason => {        
  	console.log('reason2', reason)  // reason2 3                                                                         })
promise如何串连多个操作任务?
  1. promise的then()返回一个新的promise, 可以开成then()的链式调用
  2. 通过then的链式调用串连多个同步/异步任务
new Promise((resolve, reject) => {    
	setTimeout(() => {        
		console.log("执行任务1(异步)")        
		resolve(1)
	}, 1000);
})
.then(    
	value => {        
		console.log('任务1的结果: ', value)        
		console.log('执行任务2(同步)')        
		return 2    
}).then(    
	value => {        
		console.log('任务2的结果:', value)        
		return new Promise((resolve, reject) => {            
// 启动任务3(异步)           
 			setTimeout(() => {                
 				console.log('执行任务3(异步))')                
 				resolve(3)            
 			}, 1000);        
		 })    
 })
 .then(    
	 value => {       
 	console.log('任务3的结果: ', value)    
 })
//执行任务1(异步)
//任务1的结果:  1
//执行任务2(同步)
//任务2的结果: 2
//执行任务3(异步))
//任务3的结果:  3
上一篇:DB2 SQL Error: SQLCODE=-668, SQLSTATE=57016, SQLERRMC=7


下一篇:promise详解[上]