注意注意!!! promise 非常常用,用过es6的都知道,自己稍微总结下!!
从什么是promise,如何创建,如何使用,都有哪些方法,为什么会产生promise,解决了什么问题? async await 来说:
1. promise 是es6 的新特性, 有三种状态 pending(未完成)/ fulfilled(已完成)/rejected(已失败) , 状态只能pending-fufilled/ pending-rejected 一旦确定就不能更改,单向。
2. 创建一个promise 使用new 关键字 new Promise或者Promise.resolve/Promise.reject都会返回一个promise 的实例对象; new Promise 参数是一个函数,函数有两个参数 是resolve, reject ; 这个函数里面可以是同步操作也可以异步操作。这个函数本身是同步调用哦。
promise 本身是同步的,不会进入到队列中,.then .catch是异步操作
执行器里面 同步方法:先改变状态 再指定回调函数,然后执行回调函数
let p = new Promise((resolve, reject) => {
console.log('1111')
resolve(2)
})
p.then(res=> {
console.log(res)
})
console.log('2222')
会先打印1111 在打印 222 说明执行器
resolve, reject) => {} 是一个同步调用
比如简单的
执行器里面异步方法: 先指定回调函数(只是指定没有执行),再改变状态,然后再执行回调函数
let hh = new Promise((resolve, reject) => {
console.log('1111')
setTimeout(() => {
resolve(2)
}, 2000)
})
console.log('2222')
hh.then(res=> {
console.log(res) // 2
})
Promise原型上 有.then方法接收的resolve和reject 中的数据(有两个回调,第一个回调是resolve 的数据,第二个是reject 的数据) .catch接收的是reject中的数据还可以捕获前面then抛出的错误,所以用.catch接收比较好,还有finally 成功还是失败都接收
同时.then/.catch/.finally 都会再次返回一个promise对象 ,如果里面是return 值 ,会被自动封装成一个已完成状态的promise, 所以可以链式调用
3. promise 的一些其他方法: Promise.all([p1,p2,...]).then(res => { res 也是一个数组}),特点就是传入的promise 的对象 全都resolve的话 才会进入.then的第一个回调函数中,如果失败会被.then的第二个回调函数或者.catch捕获
Promise.race([p1,p2,...])故名思意,谁第一个先改变状态成功/失败,决定了最终的结果状态
Promise.allSettled/ promise.any 具体见下面代码
返回的状态成功 进入.then的第一个回调函数中,如果失败会被.then的第二个回调函数或者.catch捕获
Promise.resolve 返回一个成功/失败的promoise 对象, 如果传入的是一个非promise类型数据,则返回的是一个成功的promise对象;如果传入的是一个promise类型对象,则返回的是该对象的成功/失败状态;
Promise.catch 返回的是一直是一个失败的对象,无论传什么类型对象;传什么,返回的就是什么
Promise.race:
只要p1、p2、p3之中有一个实例先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
传入的对象都会被执行, 但是最终只返回率先改变状态的那个promise实例的值
let p1 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('今天=====')
resolve('今天')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('天气======')
resolve('天气')
}, 500)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('很好======')
resolve('很好')
}, 3000)
})
let p Promise.race([p1,p2,p3]).then(res=>{
console.log('成功', res)
}).catch(err=>{
console.log('失败', err)
})
Promise {<pending>}
vconsole.min.js?65ce:10 天气======
vconsole.min.js?65ce:10 成功 天气
vconsole.min.js?65ce:10 今天=====
vconsole.min.js?65ce:10 很好======
Promise.all:
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。 顺序和传入的顺序一致
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
传入的数组promise 对象都会被执行 就算有reject状态的对象
let p1 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('今天=====')
resolve('今天')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('天气======')
resolve('天气')
}, 2000)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('很好======')
resolve('很好')
}, 3000)
})
Promise.all([p1,p2,p3]).then(res=>{
console.log('成功', res)
}).catch(err=>{
console.log('失败', err)
})
Promise {<pending>}
vconsole.min.js?65ce:10 今天=====
vconsole.min.js?65ce:10 天气======
vconsole.min.js?65ce:10 很好======
vconsole.min.js?65ce:10 成功 (3) ['今天', '天气', '很好']
Promise.allSettled:
allSettled 一旦发生状态变更,状态总是fulfilled, 没有rejected
let p1 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('今天=====')
resolve('今天')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('天气======')
reject('天气')
}, 500)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('很好======')
resolve('很好')
}, 3000)
})
Promise.allSettled([p1,p2,p3]).then(res=>{
console.log('成功', res)
}).catch(err=>{
console.log('失败', err)
})
Promise {<pending>}
vconsole.min.js?65ce:10 天气======
vconsole.min.js?65ce:10 今天=====
vconsole.min.js?65ce:10 很好======
vconsole.min.js?65ce:10 成功
(3) [{…}, {…}, {…}]
0: {status: 'fulfilled', value: '今天'}
1: {status: 'rejected', reason: '天气'}
2: {status: 'fulfilled', value: '很好'}
length: 3
[[Prototype]]: Array(0)
Promise.any:
只要p1 p2 p3 有一个状态是fulfilled, p的状态就是fulfilled, p的回调函数接收的是第一个先返回的fuifilled状态的值; 如果p1 p2 p3 全都是rejected 状态 p的状态才是rejected 返回的AggregateError;
let p1 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('今天=====')
resolve('今天')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('天气======')
reject('天气')
}, 500)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('很好======')
resolve('很好')
}, 3000)
})
Promise.any([p1,p2,p3]).then(res=>{
console.log('成功', res)
}).catch(err=>{
console.log('失败', err)
})
Promise {<pending>}
vconsole.min.js?65ce:10 成功 今天
let p1 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('今天=====')
reject('今天')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('天气======')
reject('天气')
}, 500)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(function() {
console.log('很好======')
reject('很好')
}, 3000)
})
let p = Promise.any([p1,p2,p3]).then(res=>{
console.log('成功', res)
}).catch(err=>{
console.log('失败', err)
})
Promise {<pending>}
vconsole.min.js?65ce:10 失败 AggregateError: All promises were rejected
4. promise本身是同步方法, then catch finally 是异步 属于微任务
5. promise 可以链式回调,原因是.then .catch .finally 还会返回一个promise 对象 ; 中断链式调用的方法 是return 一个pending状态的promise对象;return new Promise(()=>{})
6. promise 解决了什么问题? 为什么会出现它?
解决了地狱回调,那么又问什么是地狱回调 ;
回调: 将一个函数作为另一个函数的参数 使用 , 不会立即调用,在一定条件下触发。
function b(val) {
console.log('bavalval===',val)
}
function a(fn) {
setTimeout(() => {
fn('3333')
}, 2000)
}
a(b)
bavalval===3333
地狱回调:回调里面再回调
比如:
setTimeout(function () {
console.log('今天')
setTimeout(function() {
console.log('天气')
setTimeout(function() {
console.log('很好')
}, 1000)
}, 2000)
}, 1000)
输出:
今天
天气
很好
如果上面的用promise 来写的话 怎么写呢 ? .then 如果返回的是一个promise 对象就原样返回,如果不是,怎会自动封装成一个promise
let p1 = new Promise((resolve, reject) => {
setTimeout(function() {
resolve('今天')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(function() {
resolve('天气')
}, 2000)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(function() {
resolve('很好')
}, 1000)
})
p1.then(res1 => {
console.log(res1)
return p2
}).then(res2 => {
console.log(res2)
return p3
}).then(res3 => {
console.log(res3)
return res3
})
输出:
今天
天气
很好
如果用async await 如何实现
async 返回的promise 对象,自动封装; 是一个异步操作
await 后面接一个 promise 对象或者 方法 ,返回值 自动返回的是promse.then 里面的值
async function hd() {
let p1 = new Promise((resolve, reject) => {
setTimeout(function() {
resolve('今天')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(function() {
resolve('天气')
}, 2000)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(function() {
resolve('很好')
}, 1000)
})
let h1 = await p1
let h2 = await p2
let h3 = await p3
console.log(h1 + h2 + h3)
}
输出:
今天天气很好
await 后promise 对象很可能是rejected 状态,需要在try catch 里面获取异常
function promiseFn () {
return new Promise((resolve, reject)=> {
reject('错误异常')
})
}
async function doSomething() {
try {
await promiseFn();
} catch (err) {
console.log(err);
}
}
或者 另外一种简单的写法:
async function doSomething() {
await promiseFn().catch(err=> console.log(err))
}
输出:
错误异常
async await 与promise 的关系
async 返回的是一个promise 对象, 如果awiat 后面跟的是promise 对象 但是这个promise 对象的状态是pending的,后续代码都不会执行,,如果是reject, 但是没有进行catch 处理,也不会执行; 如果进行了catch 处理 会执行; 此时async 返回的对象的状态和awiat 后的对象状态一致, 否则都是成功状态, 并且成功的值 是return 的值, 默认是undefined
await 阻塞后面的代码, 后续的代码相当于一个微任务, 就相当于在.then的第一个回调函数里面执行; r
如果是一个promise 对象 ; 会等这个对象执行完毕之后 再执行 后续代码 ;
async function hd() {
let p1 = new Promise((resolve, reject) => {
setTimeout(function() {
resolve('今天')
}, 1000)
})
let h1 = await p1
console.log(h1 )
console.log('11111')
}
hd()
输出:
今天
11111
相当于
async function hd() {
new Promise((resolve, reject) => {
setTimeout(function() {
resolve('今天')
}, 1000)
}).then((res) => {
console.log(h1 )
console.log('11111')
})
}
hd()
await 后如果是一个普通对象 , 其实就是会被包装成Promise.resolve 输出
async function hd1() {
let p1 =
setTimeout(function() {
console.log('今天')
}, 1000)
let h1 = await p1
console.log('11111')
}
输出:
11111
今天
如果await 后的promise对象状态一直是pending 会导致后续代码无法执行
async function async1 () {
console.log('async1 start');
await new Promise(resolve => {
console.log('promise1')
})
console.log('async1 success');
return 'async1 end'
}
async1()
只会输出 promise1
promise1
相当于
async function async1 () {
console.log('async1 start');
new Promise(resolve => {
console.log('promise1')
}).then(res => {
console.log('async1 success');
return 'async1 end'
})
}
await 如果是reject 状态 try catch 进行处理 或者直接在await 后面的那个promise对象进行catch处理(,如果是reject, 但是没有进行catch 处理,也不会执行; 如果进行了catch 处理 会执行; )
async function async1 () {
try {
await async2();
} catch (error) {
console.log(error);
console.log('async1');
return 'async1 success'
}
}
async function async2 () {
return new Promise((resolve, reject) => {
console.log('async2')
reject('error')
})
}
async1().then(res => console.log(res))
或者
async function async1 () {
await async2().catch(err=> {console.log(err)});
console.log('async1');
return 'async1 success'
}
async function async2 () {
return new Promise((resolve, reject) => {
console.log('async2')
reject('error')
})
}
async1().then(res => console.log(res))
或者如果没有进行catch 处理 后续代码不会执行
async function async1 () {
await async2()
// 下面代码不会、输出
console.log('async1');
return 'async1 success'
}
async function async2 () {
return new Promise((resolve, reject) => {
console.log('async2')
reject('error')
})
}
async1().then(res => console.log(res))
学习参考:ES6 入门教程https://es6.ruanyifeng.com/#docs/promise%23Promise-prototype-then async 函数的含义和用法 - 阮一峰的网络日志http://www.ruanyifeng.com/blog/2015/05/async.html