1. What is promise
- Mainly used for asynchronous computing
- Asynchronous operations can be queued, executed in the desired order, and return results that meet the expectations
- You can pass and manipulate promises between objects, helping us deal with queues
2. The problem of asynchronous callback:
- The previous processing of asynchrony was handled in the form of a pure callback function
- It is easy to enter the callback hell, depriving the function of the ability to return
- The problem can be solved, but it is difficult to read and maintain
- A little carelessness will lead to callback hell -deep nesting level, difficult to maintain
3. Introduction to promise
- A promise is an object. The difference between an object and a function is that an object can save state, but a function cannot (except closures)
- Does not deprive the function of the ability to return, so there is no need to pass the callback layer by layer, callback to obtain data
- Code style, easy to understand and easy to maintain
- Consolidation of multiple asynchronous waits is easy to solve
4. Detailed Promise
The role of resolve is to change the state of the Promise object from "unfinished" to " successful " (that is, from pending to resolved), call when the asynchronous operation succeeds, and pass the result of the asynchronous operation as a parameter; the
role of reject is , Change the state of the Promise object from "unfinished" to " failed " (that is, from pending to rejected), call when the asynchronous operation fails, and pass the error reported by the asynchronous operation as a parameter.
A promise has three states:
- pending [to be determined] initial state
- fulfilled [fulfilled] operation succeeded
- rejected [Rejected] Operation failed
When the promise state changes , the response function in **then()** will be triggered to process the subsequent steps; once the
promise state changes, it will not change .
There are only two possibilities for the state of the Promise object to change:
- Change from pending to fulfilled
- Change from pending to rejected.
As long as these two situations occur, the state will be frozen and will not change anymore.
5、.then()
- Receive two functions as parameters, representing fulfilled (success) and rejected (failure)
- .then() returns a new Promise instance, so it can be chained
- When the current Promise state changes, .then() selects a specific state response function to execute according to its final state
- The status response function can return a new promise, or other values, or if it does not return a value, we can consider it to return a null;
- If a new promise is returned, the next level .then() will be executed after the state of the new promise changes
- If any other value is returned, the next level will be executed immediately.then()
6. Two methods of error handling:
Promise will automatically catch the internal exception and hand it to the rejected response function for processing.
(1) The first error handling
<script>
new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('bye')
},2000)
}).then((val)=>{
console.log(val)
},(err)=>{
console.log("Error",error)
})
</script>
(2) The second type of error handling
<script>
new Promise((resolve)=>{
setTimeout(()=>{
throw new Error('bye')
},2000)
}).then((val)=>{
console.log(val)
}).catch(error=>{
console.log("Error",error)
})
</script>
第一种:reject('错误信息').then(() => {}, () => {错误处理逻辑})
第二种:throw new Error('错误信息').catch( () => {错误处理逻辑})
It is recommended to use the second method, which is more clear and easy to read, and can capture all the previous errors (can capture N then callback errors)
7, the usage of promise
(1) Common usage:
Asynchronous operation and timer are put together. If the timer is triggered first, it will be considered as a timeout and the user will be notified;
例如:我们要从远程的服务家在资源如果5000ms还没有加载过来我们就告知用户加载失败
(2) Usage in reality
The callback is packaged as a Promise, which has two obvious benefits:
- Good readability
- The returned result can be added to any Promise queue
8. Comparison of callback hell and promise
(1) Callback hell
/***
第一步:找到北京的id
第二步:根据北京的id -> 找到北京公司的id
第三步:根据北京公司的id -> 找到北京公司的详情
目的:模拟链式调用、回调地狱
***/
// 回调地狱
// 请求第一个API: 地址在北京的公司的id
$.ajax({
url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/city',
success (resCity) {
let findCityId = resCity.filter(item => {
if (item.id == 'c1') {
return item
}
})[0].id
$.ajax({
// 请求第二个API: 根据上一个返回的在北京公司的id “findCityId”,找到北京公司的第一家公司的id
url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/position-list',
success (resPosition) {
let findPostionId = resPosition.filter(item => {
if(item.cityId == findCityId) {
return item
}
})[0].id
// 请求第三个API: 根据上一个API的id(findPostionId)找到具体公司,然后返回公司详情
$.ajax({
url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/company',
success (resCom) {
let comInfo = resCom.filter(item => {
if (findPostionId == item.id) {
return item
}
})[0]
console.log(comInfo)
}
})
}
})
}
})
(2) Promise writing
// Promise 写法
// 第一步:获取城市列表
const cityList = new Promise((resolve, reject) => {
$.ajax({
url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/city',
success (res) {
resolve(res)
}
})
})
// 第二步:找到城市是北京的id
cityList.then(res => {
let findCityId = res.filter(item => {
if (item.id == 'c1') {
return item
}
})[0].id
findCompanyId().then(res => {
// 第三步(2):根据北京的id -> 找到北京公司的id
let findPostionId = res.filter(item => {
if(item.cityId == findCityId) {
return item
}
})[0].id
// 第四步(2):传入公司的id
companyInfo(findPostionId)
})
})
// 第三步(1):根据北京的id -> 找到北京公司的id
function findCompanyId () {
let aaa = new Promise((resolve, reject) => {
$.ajax({
url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/position-list',
success (res) {
resolve(res)
}
})
})
return aaa
}
// 第四步:根据上一个API的id(findPostionId)找到具体公司,然后返回公司详情
function companyInfo (id) {
let companyList = new Promise((resolve, reject) => {
$.ajax({
url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/company',
success (res) {
let comInfo = res.filter(item => {
if (id == item.id) {
return item
}
})[0]
console.log(comInfo)
}
})
})
}