学习了coderwhy的JavaScript高级语法视频课的笔记
如有错误或者不合适的地方,敬请见谅,欢迎指出和拓展,谢谢各位了
1. 异步请求的处理-方式一(切入点)
// 模拟网络的异步请求
function requestData(url, successCallback, failureCallback) {
setTimeout(() => {
if (url === 'aaa') {
const names = ['a', 'b', 'c']
successCallback(names)
} else {
const errMessage = '请求失败,url地址不正确'
failureCallback(errMessage)
}
}, 1000)
}
requestData(
'aaa',
res => {
console.log(res)
},
err => {
console.log(err)
}
)
/**
* 这种回调的方式有很多的弊端:
* 1> 如果是我们自己封装的requestData,那么我们在封装的时候必须要自己设计好callback名称, 并且使用好
* 2> 如果我们使用的是别人封装的requestData或者一些第三方库,
那么我们必须去看别人的源码或者文档, 才知道它这个函数需要怎么去获取到结果
*/
2. Promise的基本使用
- 在通过new创建Promise对象时,我们需要传入一个回调函数,我们称之为executor:
- 这个回调函数会被立即执行,并且给传入另外两个回调函数resolve、reject;
- 当我们调用resolve回调函数时,会执行Promise对象的then方法传入的第一个回调函数;
- 当我们调用reject回调函数时,会执行Promise对象的then方法传入的第二个回调函数,或catch方法传入的回调函数(catch方法后面再讲)。
const promise = new Promise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
promise.then(
res => {
console.log(res)
},
err => {
console.log(err)
}
)
上面Promise使用过程,我们可以将它划分成三个状态:
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝;
- 当执行executor中的代码时,处于该状态;
- 已兑现(fulfilled): 意味着操作成功完成,我们也可以称之为已决议(resolved);
- 执行了resolve时,处于该状态;
- 已拒绝(rejected): 意味着操作失败;
- 执行了reject时,处于该状态。
注意: Promise状态一旦确定下来, 那么就是不可更改的(锁定)
3. 异步请求的处理-方式二(Promise)
// 模拟网络的异步请求
function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url === 'aaa') {
const names = ['a', 'b', 'c']
resolve(names)
} else {
const errMessage = '请求失败,url地址不正确'
reject(errMessage)
}
}, 1000)
})
}
const promise = requestData('aaa')
promise.then(
res => {
console.log(res)
},
err => {
console.log(err)
}
)
4. Promise的resolve的参数
/**
* resolve(参数)
* 1、普通的值或者对象 pending -> fulfilled
* 2、传入一个Promise
* 那么当前的Promise的状态会由传入的Promise来决定
* 相当于状态进行了移交
* 3、传入一个对象, 并且这个对象有实现then方法(并且这个对象是实现了thenable接口)
* 那么也会执行该then方法, 并且又该then方法决定后续状态
*/
// 1、普通的值或者对象 pending -> fulfilled
const promise = new Promise((resolve, reject) => {
resolve(111)
})
promise.then(
res => {
console.log(res) //111
},
err => {}
)
// 2、传入一个Promise,那么当前的Promise的状态会由传入的Promise来决定,相当于状态进行了移交
const promiseResolve = new Promise((resolve, reject) => {
reject(222)
})
const promise2 = new Promise((resolve, reject) => {
resolve(promiseResolve)
})
promise2.then(
res => {},
err => {
console.log(err) //222
}
)
// 3、传入一个对象, 并且这个对象有实现then方法(并且这个对象是实现了thenable接口),
// 那么也会执行该then方法, 并且又该then方法决定后续状态
const obj = {
then: function (resolve, reject) {
reject(333)
}
}
const promise3 = new Promise((resolve, reject) => {
resolve(obj)
})
promise3.then(
res => {},
err => {
console.log(err) //333
}
)
5. Promise的对象方法
(1). then方法
- 事实上then方法也是会返回一个Promise对象的,所以catch方法后面我们可以继续调用then方法或者catch方法
// 1.同一个Promise可以被多次调用then方法
// 当我们的resolve方法被回调时, 所有的then方法传入的回调函数都会被调用
const promise = new Promise((resolve, reject) => {
resolve('xxxx')
})
promise.then(res => {
console.log(res) //xxx
})
promise.then(res => {
console.log(res) //xxx
})
// 2.then方法传入的 "回调函数: 可以有返回值,默认return是undefined
// then方法本身也是有返回值的, 它的返回值是Promise
// (1)如果我们返回的是一个普通值(数值/字符串/普通对象/undefined),
// 那么这个普通的值被作为一个新的Promise的resolve值
const promise21 = new Promise((resolve, reject) => {
resolve('xxxx')
})
promise21
.then(res => {
return 111
})
.then(res => {
console.log(res) //111
})
// (2)如果我们返回的是一个Promise
const promise22 = new Promise((resolve, reject) => {
resolve('xxx')
})
promise22
.then(res => {
return new Promise((resolve, reject) => {
resolve(222)
})
})
.then(res => {
console.log(res) //222
})
// (3)如果返回的是一个对象, 并且该对象实现了thenable
const promise23 = new Promise((resolve, reject) => {
resolve('xxx')
})
promise23
.then(res => {
return {
then: function (resolve, reject) {
resolve(333)
}
}
})
.then(res => {
console.log(res) //333
})
(2). catch方法
- 事实上catch方法也是会返回一个Promise对象的,所以catch方法后面我们可以继续调用then方法或者catch方法
// 1.当executor抛出异常时, 也是会调用错误(拒绝)捕获的回调函数的
const promise = new Promise((resolve, reject) => {
throw new Error('错误')
})
promise.then(undefined, err => {
console.log(err)
})
// 2.通过catch方法来传入错误(拒绝)捕获的回调函数
const promise2 = new Promise((resolve, reject) => {
throw new Error('错误2')
// resolve(222)
})
promise2.catch(err => {
console.log(err)
})
promise2
.then(res => {
throw new Error('错误22')
})
.catch(err => {
//throw new Error('错误2'),如果resolve(222)则是throw new Error('错误22')
console.log(err)
})
// 3.拒绝捕获的问题
const promise3 = new Promise((resolve, reject) => {
// resolve(333)
reject('错误3')
})
// 这里then方法和catch方法是两次独立的调用,所以then方法中没有捕获异常的方法而报错
promise3.then(res => {
console.log(res)
})
promise3.catch(err => {
console.log(err)
})
// 4.catch方法的返回值
//事实上catch方法也是会返回一个Promise对象的,所以catch方法后面我们可以继续调用then方法或者catch方法
const promise4 = new Promise((resolve, reject) => {
reject(111)
})
promise4
.then(res => {})
.catch(err => {
// return 222
return new Promise((resolve, reject) => {
resolve(222)
// reject(222)
})
})
.then(
res => {
console.log(res)
},
err => {
console.log(err)
}
)
promise4
.then(
res => {},
err => {
// return 222333
return new Promise((resolve, reject) => {
resolve(222333)
// reject(222333)
})
}
)
.then(
res => {
console.log(res)
},
err => {
console.log(err)
}
)
(3). finally方法
- finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象无论变成fulfilled还是reject状态,最终都会被执行的代码。
- finally方法是不接收参数的,因为无论前面是fulfilled状态,还是reject状态,它都会执行。
const promise = new Promise((resolve, reject) => {
reject(111)
})
promise
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
.finally(() => {
console.log('finally')
})
6. Promise的类方法
- 前面我们学习的then、catch、finally方法都属于Promise的实例方法,都是存放在Promise的prototype上的。
(1). resolve类方法
- 有时候我们已经有一个现成的内容了,希望将其转成Promise来使用,这个时候我们可以使用 Promise.resolve方法来完成。
- resolve参数的形态:
- 情况一:参数是一个普通的值或者对象;
- 情况二:参数本身是Promise;
- 情况三:参数是一个thenable —— {then:functio(resolve,reject){...}}。
//转成promise对象
// 1、
function foo() {
const obj = {
name: 'xxx',
age: 18
}
return new Promise((resolve, reject) => {
resolve(obj)
})
}
foo().then(res => {
console.log(res)
})
// 2、
const promise2 = Promise.resolve({
name: 'xxx',
age: 18
})
//相当于
// const promise2 = new Promise((resolve, reject) => {
// resolve(obj)
// })
promise2.then(res => {
console.log(res)
})
(2). reject类方法
- reject方法类似于resolve方法,只是会将Promise对象的状态设置为reject状态。
- 注意: Promise.reject传入的参数无论是什么形态,都会直接作为reject状态的参数传递到catch的,无论传入什么值都是一样的。
const promise = Promise.reject(
new Promise((resolve, reject) => {
resolve('bbb')
})
)
//相当于
// const promise = new Promise((resolve, reject) => {
// reject(
// new Promise((resolve, reject) => {
// resolve('bbb')
// })
// )
// })
promise
.then(res => {})
.catch(err => {
console.log('err:' + err) //err:[object Promise]
})
(3). all类方法
- 它的作用是将多个Promise包裹在一起形成一个新的Promise;
- 新的Promise状态由包裹的所有Promise共同决定:
- 当所有的Promise状态都变成fulfilled状态时,新的Promise状态为fulfilled,并且会将所有Promise的返回值 组成一个数组;
- 当有一个Promise状态为reject时,新的Promise状态为reject,并且会将第一个reject的返回值作为参数。
// 1、
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 3000)
})
Promise.all([p1, p2, p3, '444'])
.then(res => {
console.log(res) //[ 111, 222, 222, '444' ]
})
.catch(err => {
console.log(err)
})
// 2、
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(222)
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 3000)
})
Promise.all([p1, p2, p3, '444'])
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err) //222
})
(4). allSettled类方法
- all方法有一个缺陷,当有其中一个Promise变成reject状态时,新Promise就会立即变成对应的reject状态,那么对于resolved的,以及依然处于pending状态的Promise,我们是获取不到对应的结果的。
- 在ES11(ES2020)中,添加了新的API Promise.allSettled:
- 该方法会在所有的Promise都有结果(settled),无论是fulfilled,还是reject时,才会有最终的状态;
- 并且这个Promise的结果一定是fulfilled的。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(222)
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 3000)
})
Promise.allSettled([p1, p2, p3, '444'])
.then(res => {
console.log(res)
// [
// { status: 'fulfilled', value: 111 },
// { status: 'rejected', reason: 222 },
// { status: 'fulfilled', value: 222 },
// { status: 'fulfilled', value: '444' }
// ]
})
.catch(err => {
console.log(err)
})
(5). race类方法
- 如果有一个Promise有了结果,我们就希望决定最终新Promise的状态,那么可以使用race方法:
- race是竞技、竞赛的意思,表示多个Promise相互竞争,谁先有结果,那么就使用谁的结果。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 2000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(222)
}, 1000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 3000)
})
Promise.race([p1, p2, p3])
.then(res => {
console.log(res)
})
.catch(err => {
console.log('err:' + err) //err:222
})
(6). any类方法
- any方法是ES12中新增的方法,和race方法是类似的:
- any方法会等到一个fulfilled状态,才会决定新Promise的状态;
- 如果所有的Promise都是reject的,那么也会等到所有的Promise都变成rejected状态,然后报一个AggregateError的错误。
// 1、
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(111)
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 3000)
})
Promise.any([p1, p2, p3])
.then(res => {
console.log(res) //222
})
.catch(err => {
console.log('err:' + err)
})
// 2、
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(111)
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(222)
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(222)
}, 3000)
})
Promise.any([p1, p2, p3])
.then(res => {
console.log(res) //222
})
.catch(err => {
console.log('err:' + err) //err:AggregateError: All promises were rejected
})