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
- Promise构造函数: Promise (
excutor
) {}excutor
函数: 同步执行 (resolve, reject) => {} resolve函数: 内部定义成功时我们调用的函数 value => {} reject函数: 内部定义失败时我们调用的函数 reason => {} 说明:excutor
会在Promise内部立即同步回调,异步操作在执行器中执行 Promise.prototype.then
方法: (onResolved, onRejected
) => {}onResolved函数
: 成功的回调函数 (value) => {}onRejected
函数: 失败的回调函数 (reason) => {} 说明: 指定用于得到成功value的成功回调和用于得到失败reason的失败回调 返回一个新的promise对象Promise.prototype.catch
方法: (onRejected
) => {}onRejected
函数: 失败的回调函数 (reason) => {} 说明: then()的语法糖, 相当于: then(undefined,onRejected
)Promise.resolve
方法: (value) => {} value: 成功的数据或promise对象 说明: 返回一个成功/失败的promise对象Promise.reject
方法: (reason) => {} reason: 失败的原因 说明: 返回一个失败的promise对象Promise.all
方法: (promises) => {} promises: 包含n个promise的数组 说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败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如何串连多个操作任务?
- promise的then()返回一个新的promise, 可以开成then()的链式调用
- 通过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
标签:console,log,value,学习,reason,Promise,笔记,promise 来源: https://blog.csdn.net/aflylong/article/details/119426165