异步调用必须要用回调函数返回数据,进行复杂调用的时候,会出现“回调地狱”。
function sum(a, b, cb) {
setTimeout(() => {
cb(a + b)
}, 1000)
}
console.log("111111")//回调地狱
sum(123, 456, (result) => {
sum(result, 7, (result) => {
sum(result, 7, (result) => {
console.log(result)
})
})
})
console.log(22222)
同步代码用return,异步代码用回调函数。因为return是立刻返回的,异步代码的结果就返回不出去。
Promise
- Promise可以帮助我们解决异步中的回调函数的问题
- Promise就是一个用来存储数据的容器
它拥有着一套特殊的存取数据的方式
这个方式使得它里边可以存储异步调用的结果
创建Promise
// 创建Promise时,构造函数中需要一个函数作为参数
// Promise构造函数的回调函数,它会在创建Promise时调用,调用时会有两个参数传递进去
向Promise中存储数据(then,catch)
// resolve 和 reject 是两个函数,通过这两个函数可以向Promise中存储数据
// resolve在执行正常时存储数据,reject在执行错误时存储数据
通过函数来向Promise中添加数据,好处就是可以用来添加异步调用的数据
const promise = new Promise((resolve, reject) => {
// reject("哈哈")
setTimeout(() => {
resolve("哈哈")
}, 2000)
// throw new Error("哈哈,出错了")
// resolve("resolve返回的数据")
})
从Promise中读取数据
- 可以通过Promise的实例方法then来读取Promise中存储的数据
- then需要两个回调函数作为参数,回调函数用来获取Promise中的数据
通过resolve存储的数据,会调用第一个函数返回,
可以在第一个函数中编写处理数据的代码
通过reject存储的数据或者出现异常时,会调用第二个函数返回
可以在第二个函数中编写处理异常的代码
promise.then((result) => {
console.log("1", result)
}, (reason) => {
console.log("2", reason)
})
Promise中两个隐藏属性:
PromiseResult
- 用来存储数据
PromiseState
- 记录Promise的状态(三种状态)
pending (进行中)
fulfilled(完成) 通过resolve存储数据时
rejected(拒绝,出错了) 出错了或通过reject存储数据时
- state只能修改一次,修改以后永不会在变
流程:
当Promise创建时,PromiseState初始值为pending,
当通过resolve存储数据时 PromiseState 变为fulfilled(完成)
PromiseResult变为存储的数据
当通过reject存储数据或出错时 PromiseState 变为rejected(拒绝,出错了)
PromiseResult变为存储的数据 或 异常对象
当我们通过then读取数据时,相当于为Promise设置了回调函数,
如果PromiseState变为fulfilled,则调用then的第一个回调函数来返回数据
如果PromiseState变为rejected,则调用then的第二个回调函数来返回数据
catch() 用法和then类似,但是只需要一个回调函数作为参数
catch()中的回调函数只会在Promise被拒绝时才调用
catch() 相当于 then(null, reason => {})
catch() 就是一个专门处理Promise异常的方法
finally()
- 无论是正常存储数据还是出现异常了,finally总会执行
- 但是finally的回调函数中不会接收到数据
- finally()通常用来编写一些无论成功与否都要执行代码
promise2.catch(reason => {
console.log(222222)
})
promise2.finally(()=>{
console.log("没有什么能够阻挡我执行的!")
})
为什么要用promise来存储异步调用的结果
Promise就是一个用来存储数据对象
// 但是由于Promise存取的方式的特殊,所以可以直接将异步调用的结果存储到Promise中
// 对Promise进行链式调用时
// 后边的方法(then和catch)读取的上一步的执行结果
// 如果上一步的执行结果不是当前想要的结果,则跳过当前的方法
当Promise出现异常时,而整个调用链中没有出现catch,则异常会向外抛出
const promise = new Promise((resolve, reject) => {
reject("周一到周五19点,不见不散")
})
promise
.then(r => console.log("第一个then", r))
.catch(r => {
throw new Error("报个错玩")
console.log("出错了")
return "嘻嘻"
})
.then(r => console.log("第二个then", r))
.catch(r => {
console.log("出错了")
})
/*
promise中的
then (return new Promise())
catch
- 这三个方法都会返回一个新的Promise,
Promise中会存储回调函数的返回值
finally
- finally的返回值,不会存储到新的Promise中
*/
// promise
// .then(result => {
// console.log("回调函数", result)
// return "锄禾日当午"
// })
// .then(result => {
// console.log("第二个then", result)
// return "超哥真快乐"
// })
// .then(result => {
// console.log(result)
// })
// promise.then(result => {
// console.log(result)
// }, reason => {
// console.log("出错了", reason)
// })
// function sum(a, b, cb) {
// setTimeout(() => {
// cb(a + b)
// }, 1000);
// }
function sum(a, b) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a + b)
}, 1000)
})
}
// sum(123, 456).then(result => {
// sum(result, 7).then(result =>{
// sum(result, 8).then(result => {
// console.log(result)
// })
// })
// })
// sum(123, 456)
// .then(result => result + 7)
// .then(result => result + 8)
// .then(result => console.log(result))
静态方法
静态方法
Promise.resolve() 创建一个立即完成的Promise
Promise.reject() 创建一个立即拒绝的Promise
Promise.all([...]) 同时返回多个Promise的执行结果
其中有一个报错,就返回错误
Promise.allSettled([...]) 同时返回多个Promise的执行结果(无论成功或失败)
{status: 'fulfilled', value: 579}
{status: 'rejected', reason: '哈哈'}
Promise.race([...]) 返回执行最快的Promise(不考虑对错)
Promise.any([...]) 返回执行最快的完成的Promise
Promise.all([
sum(123, 456),
sum(5, 6),
Promise.reject("哈哈"),
sum(33, 44)
]).then(r => {
console.log(r)
})
Promise.allSettled([
sum(123, 456),
sum(5, 6),
Promise.reject("哈哈"),
sum(33, 44)
]).then(r => {
console.log(r)
})
Promise.race([
Promise.reject(1111),
sum(123, 456),
sum(5, 6),
sum(33, 44)
]).then(r => {
console.log(r)
}).catch(r => {
console.log("错误")
})
// Promise.any([
// Promise.reject(1111),
// Promise.reject(2222),
// Promise.reject(3333),
// ]).then(r => {
// console.log(r)
// }).catch(r => {
// console.log("错误", r)
// })