.then的链式调用
- promise.then()可以接受两个参数,都是函数,第一个参数为promise状态成功时执行,第二个参数为promise状态失败时执行,在.then的时候就会立即执行
- promise.then()也会返回一个promise,并把参数函数的返回值传给返回的promise,如果是执行第一个参数函数也就是resolve,那返回的promise也是成功状态的
- 如果是执行第二个参数也就是reject,那返回的promise就是失败状态的
- 如果是执行第一个函数也就是resolve,那这个函数返回的值就是返回的promise resolve的值,就是.then的参数
- Promise.resolve也会返回一个promise实例,并且状态为resolved的,当这个返回的promise执行.then方法的时候,会立即执行第一个参数函数,Promise.resolve的参数就会是返回promise.then方法第一个参数函数的参数、
实例:
let a = {
foo: 'bar'
}
let promise = Promise.resolve(a) // 声明一个成功状态的promise,并把a对象当成resolved的值
// 对promise重新赋值四次,会立即执行testRes方法
promise = promise.then(testRes)
promise = promise.then(testRes)
promise = promise.then(testRes)
promise = promise.then(testRes)
// 对a对象进行处理,为随机赋值一对key-value,再将返回出去
let testRes = function (a) {
a[`test${parseInt(Math.random() * 100)}`] = parseInt(Math.random() * 10)
return a
}
当执行第一个promise = promise.then(testRes)时,会立即执行testRes方法,而参数就是初始化的a,因为在上面,promise的初始值就是一个成功状态的promise,并且resolve的值是a,赋值后的promise也是一个promise对象,并且resolve的值就是处理一次的a对象,最后打印:
promise.then((res) => {
console.log(res)
//{foo: "bar", test90: 5, test35: 9, test23: 8, test44: 9}
})
这个用法是axios库的拦截器中使用到,使用过的朋友应该知道,axios的拦截器就是将config或者response进行一层一层的传递,处理。
与await结合
直接看例子:
async function test() {
// 原始写法
const promise = new Promise((resolve, reject) => {
let num = parseInt(Math.random() * 10)
if (num >= 5) {
setTimeout(() => {
resolve(`${num}成功`)
}, 1000)
} else {
setTimeout(() => {
reject(`${num}失败`)
}, 1000)
}
})
promise.then((res) => {
// console.log(res) // 成功
}).catch((err) => {
// console.log(err) // 捕获错误,不会报错
})
/*
* await无返回值情况
* const result = await promise这种写法,如果promise成功的情况,那result会拿到.then成功函数的参数也就是上面的res
* 如果promise失败的情况,那会报错,不会再往下执行
*/
const result = await promise
console.log(result)
/*
* await有返回值情况
*这种通过promise返回的情况,result拿到就是具体返回的内容,能捕获错误不会报错,推荐这种写法
*/
const result = await promise.then((res) => {
return res
}).catch((err) => {
return err
})
console.log(result)
}
test()
推荐最后一种写法
异步分离
指的是定义一个pending状态,然后先定好promise成功情况后操作,然后由外部控制这个promise什么时候变成resolved状态,去执行.then操作,先看一个最简单的例子:
// 定义一个变量来控制promise的状态:
let timingFn
let promise = new Promise((resolve, reject) => {
timingFn = resolve // 将resolve函数赋值给外部的变量
})
promise.then((res) => {
console.log(res) // 两秒后打印11
})
// 外部决定什么时候resolve
setTimeout(() => {
timingFn('11')
}, 2000)
再看一个较为复杂的例子,由内部控制promise resolve执行的逻辑,外部只是控制promise的状态,主要运用到函数的参数知识:
let timingFn // 外部控制状态的变量
class TestWrapperFn {
promise
constructor(wrapperFn) {
let resolveFn
this.promise = new Promise((resolve, reject) => {
resolveFn = resolve
})
/**
* wrapperFn 由外部传入,会有一个参数, 这个参数外部无法写逻辑, 由内部定义的
* 这个参数也是一个函数,这里内部给定义成promise的resolve函数,这个函数在内部只是定义,不会执行,由外部执行
* 当这个函数在外部执行了,promise的状态就变成resolved,会执行then方法
*/
wrapperFn(() => { // 这里的参数函数只是定义,不会执行
resolveFn('test')
})
}
}
// 这里的Fn2就是上面类中定义的wrapperFn的参数函数
const testWrapperFn = new TestWrapperFn(function wrapperFn(fn2) {
timingFn = fn2
})
setTimeout(() => {
timingFn()
}, 2000)
testWrapperFn.promise.then((res) => {
console.log(res) // 两秒后打印test
})
这就是超人鸭这次分享的几个promise用法,主要是在学习axios库时总结的dome,感觉自己对promise的理解也是非常浅,如果你对promise有更好的理解,欢迎指教。
网友评论