今天给大家分享promise,笔者将从早期的异步代码的困境、promise出现解决了什么问题、异步回调地狱的终极方案并且实现async await的核心语法,其实async/await只是generator+promise的一个变种而已。
promise
。function requestData(url) {
setTimeout(() => {
if (url === 'iceweb.io') {
return '请求成功'
}
return '请求失败'
}, 3000)
}
const result = requestData('iceweb.io')
console.log(result) //undefined
js
代码的执行顺序,而不是是想当然的,代码其实并不是按照你书写的顺序执行的。undefined呢
?requestData
函数,开始执行函数。遇到了异步操作不会阻塞后面代码执行的,因为js是单线程的,所以你写的return
成功或者失败并没有返回,那我这个函数中,抛开异步操作,里面并没有返回值,所以值为undefined
。function requestData(url, successCB, failureCB) {
setTimeout(() => {
if (url === 'iceweb.io') {
successCB('我成功了,把获取到的数据传出去', [{name:'ice', age:22}])
} else {
failureCB('url错误,请求失败')
}
}, 3000)
}
//3s后 回调successCB
//我成功了,把获取到的数据传出去 [ { name: 'ice', age: 22 } ]
requestData('iceweb.io', (res, data) => console.log(res, data), rej => console.log(rej))
//3s后回调failureCB
//url错误,请求失败
requestData('icexxx.io', res => console.log(res) ,rej => console.log(rej))
Promise
(承诺),给予调用者一个承诺,过一会返回数据给你,就可以创建一个promise对象new
一个promise
,此时我们需要传递一个回调函数,这个函数为立即执行的,称之为(executor)reslove
,reject
(函数可以进行传参)reslove
函数,会回调promise对象的.then函数reject
函数,会回调promise对象的.catche函数new Promise((resolve, reject) => {
console.log(`executor 立即执行`)
})
executor
是立即执行的function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url === 'iceweb.io') {
//只能传递一个参数
resolve('我成功了,把获取到的数据传出去')
} else {
reject('url错误,请求失败')
}
}, 3000)
})
}
//1. 请求成功
requestData('iceweb.io').then(res => {
//我成功了,把获取到的数据传出去
console.log(res)
})
//2. 请求失败
//2.2 第一种写法
//url错误,请求失败
requestData('iceweb.org').then(res => {},rej => console.log(rej))
//2.2 第二种写法
//url错误,请求失败
requestData('iceweb.org').catch(e => console.log(e))
executor
(会被Promise类中自动执行)resolve
函数,失败的时候调用reject
函数,把需要的参数传递出去。.then
方法中可以传入两个回调,您也可以查看Promise/A+规范fulfilled
的回调rejected
的回调统一规范,可以增强阅读性和扩展性
小幅度减少回调地狱
promise
的时候,给它一个承诺,我们可以将他划分为三个阶段resolve
函数则代表了已兑现状态reject
函数则代表了已拒绝状态思考以下代码:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败')
resolve('成功')
}, 3000);
})
promise.then(res => console.log(res)).catch(err => console.log(err))
//失败
reject
之后,在调用resolve
是无效的,因为状态已经发生改变,并且是不可逆的。resolve
传入一个普通的值或者对象,只能传递接受一个参数,那么这个值会作为then
回调的参数const promise = new Promise((resolve, reject) => {
resolve({name: 'ice', age: 22})
})
promise.then(res => console.log(res))
// {name: 'ice', age: 22}
resolve
中传入的是另外一个Promise
,那么这个新Promise
会决定原Promise
的状态const promise = new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ice')
}, 3000);
}))
})
promise.then(res => console.log(res))
//3s后 ice
resolve
中传入的是一个对象,并且这个对象有实现then
方法,那么会执行该then
方法,then
方法会传入resolve
,reject
函数。此时的promise
状态取决于你调用了resolve
,还是reject
函数。这种模式也称之为: thenableconst promise = new Promise((resolve, reject) => {
resolve({
then(res, rej) {
res('hi ice')
}
})
})
promise.then(res => console.log(res))
// hi ice
Promise.prototype
上的方法,也就是Promise的显示原型上,当我new Promise的时候,会把返回的改对象的 promise[[prototype]](隐式原型) === Promise.prototype (显示原型)then
方法可以接受参数,一个参数为成功的回调,另一个参数为失败的回调,前面重构requestData
中有演练过。const promise = new Promise((resolve, reject) => {
resolve('request success')
// reject('request error')
})
promise.then(res => console.log(res), rej => console.log(rej))
//request success
null
或""
占位const promise = new Promise((resolve, reject) => {
// resolve('request success')
reject('request error')
})
promise.then(null, rej => console.log(rej))
//request error
const promise = new Promise((resolve, reject) => {
resolve('hi ice')
})
promise.then(res => ({name:'ice', age:22}))
.then(res => console.log(res))
//{name:'ice', age:22}
then
方法是有返回值的,它的返回值是promise
,但是是promise
那它的状态如何决定呢?接下来让我们一探究竟。const promise = new Promise((resolve, reject) => {
resolve('hi ice')
})
promise.then(res => ({name:'ice', age:22}))
.then(res => console.log(res))
//{name:'ice', age:22}
Promise.resolve
,并且把返回值作为实参传递到then
方法中。undefined
const promise = new Promise((resolve, reject) => {
resolve('hi ice')
})
promise.then(res => {
return new Promise((resolve, reject) => {
resolve('then 的返回值')
})
}).then(res => console.log(res))
//then 的返回值
promise
对象,状态和你调用resolve
,还是reject
有关const promise = new Promise((resolve, reject) => {
resolve('hi ice')
})
promise.then(res => {
return {
then(resolve, reject) {
resolve('hi webice')
}
}
}).then(res => console.log(res))
//hi webice
resolve
,还是reject
const promise = new Promise((resolve, reject) => {
reject('ice error')
})
promise.catch(err => console.log(err))
promise.catch(err => console.log(err))
promise.catch(err => console.log(err))
//ice error
//ice error
//ice error
resolve
还是reject
const promise = new Promise((resolve, reject) => {
reject('ice error')
})
promise.catch(err => ({name:'ice', age: 22})).then(res => console.log(res))
//{name:'ice', age: 22}
const promise = new Promise((resolve, reject) => {
reject('ice error')
})
promise.catch(err => {
return new Promise((resolve, reject) => {
reject('ice error promise')
})
}).catch(res => console.log(res))
//ice error promise
new Promise()
调用了reject
函数,则会被catch
捕获到const promise = new Promise((resolve, reject) => {
reject('ice error')
})
promise.catch(err => {
return {
then(resolve, reject) {
reject('ice error then')
}
}
}).catch(res => console.log(res))
//ice error then
finally
方法const promise = new Promise((resolve, reject) => {
resolve('hi ice')
})
promise.then(res => console.log(res)).finally(() => console.log('finally execute'))
//finally execute
Promise.resolve('ice')
//等价于
new Promise((resolve, reject) => resolve('ice'))
Promise.reject('ice error')
//等价于
new Promise((resolve, reject) => reject('ice error'))
fulfilled 状态
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi ice')
}, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi panda')
}, 2000);
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi grizzly')
}, 3000);
})
Promise.all([promise1, promise2, promise3]).then(res => console.log(res))
//[ 'hi ice', 'hi panda', 'hi grizzly' ]
resolve
状态的时候才会调用.then
方法。.catch
方法rejected状态
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi ice')
}, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('hi panda')
}, 2000);
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi grizzly')
}, 3000);
})
Promise.all([promise1, promise2, promise3]).then(res => console.log(res)).catch(err => console.log(err))
//hi panda
Promise.all
有一个缺陷,就是当遇到一个rejected的状态,那么对于后面是resolve
或者reject
的结果我们是拿不到的Promise.allSettled
,无论状态是fulfilled/rejected都会把参数返回给我们所有promise都有结果
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('hi ice')
}, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi panda')
}, 2000);
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('hi grizzly')
}, 3000);
})
Promise.allSettled([promise1, promise2, promise3]).then(res => console.log(res))
/* [
{ status: 'rejected', reason: 'hi ice' },
{ status: 'fulfilled', value: 'hi panda' },
{ status: 'rejected', reason: 'hi grizzly' }
] */
其中一个promise没有结果
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('hi ice')
}, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi panda')
}, 2000);
})
const promise3 = new Promise((resolve, reject) => {})
Promise.allSettled([promise1, promise2, promise3]).then(res => console.log(res))
// 什么都不打印
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('hi error')
}, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi panda')
}, 2000);
})
Promise.race([promise1, promise2])
.then(res => console.log(res))
.catch(e => console.log(e))
//hi error
AggregateError
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('hi error')
}, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hi panda')
}, 2000);
})
Promise.any([promise1, promise2])
.then(res => console.log(res))
.catch(e => console.log(e))
//hi panda
function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url.includes('iceweb')) {
resolve(url)
} else {
reject('请求错误')
}
}, 1000);
})
}
requestData('iceweb.io').then(res => {
requestData(`iceweb.org ${res}`).then(res => {
requestData(`iceweb.com ${res}`).then(res => {
console.log(res)
})
})
})
//iceweb.com iceweb.org iceweb.io
function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url.includes('iceweb')) {
resolve(url)
} else {
reject('请求错误')
}
}, 1000);
})
}
requestData('iceweb.io').then(res => {
return requestData(`iceweb.org ${res}`)
}).then(res => {
return requestData(`iceweb.com ${res}`)
}).then(res => {
console.log(res)
})
//iceweb.com iceweb.org iceweb.io
function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url.includes('iceweb')) {
resolve(url)
} else {
reject('请求错误')
}
}, 1000);
})
}
function* getData(url) {
const res1 = yield requestData(url)
const res2 = yield requestData(res1)
const res3 = yield requestData(res2)
console.log(res3)
}
const generator = getData('iceweb.io')
generator.next().value.then(res1 => {
generator.next(`iceweb.org ${res1}`).value.then(res2 => {
generator.next(`iceweb.com ${res2}`).value.then(res3 => {
generator.next(res3)
})
})
})
//iceweb.com iceweb.org iceweb.io
getData
已经变为同步的形式,可以拿到我最终的结果了。那么很多同学会问,generator一直调用.next
不是也产生了回调地狱吗?function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url.includes('iceweb')) {
resolve(url)
} else {
reject('请求错误')
}
}, 1000);
})
}
function* getData() {
const res1 = yield requestData('iceweb.io')
const res2 = yield requestData(`iceweb.org ${res1}`)
const res3 = yield requestData(`iceweb.com ${res2}`)
console.log(res3)
}
//自动化执行 async await相当于自动帮我们执行.next
function asyncAutomation(genFn) {
const generator = genFn()
const _automation = (result) => {
let nextData = generator.next(result)
if(nextData.done) return
nextData.value.then(res => {
_automation(res)
})
}
_automation()
}
asyncAutomation(getData)
//iceweb.com iceweb.org iceweb.io
async await
的一个变种而已.next
方法function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url.includes('iceweb')) {
resolve(url)
} else {
reject('请求错误')
}
}, 1000);
})
}
async function getData() {
const res1 = await requestData('iceweb.io')
const res2 = await requestData(`iceweb.org ${res1}`)
const res3 = await requestData(`iceweb.com ${res2}`)
console.log(res3)
}
getData()
//iceweb.com iceweb.org iceweb.io
getData
生成器函数函数,改为async
函数,yeild
的关键字替换为await
就可以实现异步代码同步写法了。async function sayHi() {
console.log('hi ice')
}
sayHi()
//hi ice
异步函数的返回值和普通返回值有所区别
undefined
Promise.resolve
(返回值)resolve
,或者reject
有关异步函数中可以使用await
关键字,现在在全局也可以进行await
,但是不推荐。会阻塞主进程的代码执行
async function sayHi() {
console.log(res)
}
sayHi().catch(e => console.log(e))
//或者
async function sayHi() {
try {
console.log(res)
}catch(e) {
console.log(e)
}
}
sayHi()
//ReferenceError: res is not defined
await
关键字,普通函数不行resolve或者reject
await
后续的代码,所以await
后面的代码,相当于包括在.then
方法的回调中,如果状态变为rejected,你则需要在函数内部try catch
,或者进行链式调用进行.catch
操作function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url.includes('iceweb')) {
resolve(url)
} else {
reject('请求错误')
}
}, 1000);
})
}
async function getData() {
const res = await requestData('iceweb.io')
console.log(res)
}
getData()
// iceweb.io
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:support@lcayun.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。