前言
前几天写代码的时候遇到了一个坑,async函数里面return的是一个promise对象,而不是我当时想要的某个值
getDeviceForm = async (formId, formName) => {
const { storeId } = this.props.param;
const { formMap } = this.state;
const { ret, data } = await Request.get({
uri: Request.getApiAddress('ENGINEERING', 'operation/form/device'),
data: {
formId,
storeId,
},
useLoading: true,
});
return data;
}
本想return一个对象,结果却返回给我一个promise对象,无论在后面加什么then函数return的值都是一个promise对象,
async函数会返回promise对象,把return的值放在promise里面
因此觉得还是没有理解async的原理.....😂回顾一下promise的知识点
一、promise的原理
promise就是一个异步得容器,里面保存着一个异步事件(在未来才会结束得事件,promise就是一个对象,从它可以获取异步操作得结果。
promise有两个特点
(1)promise不受外界影响,它代表一个异步操作,有三种状态:pending,fulfilled,rejected。只有异步操作的结果可以决定当前是哪种状态
(2)一旦状态改变,就不会在变化,任何时候都可以得到这个值,promise对象的状态改变只有两种,pending变为fulfilled,pending变为rejected,只要着两种情况发生,状态就凝固不变了,这时就称resolved
二、基本用法
2.1es6规定Promise对象是一个构造函数,用来生成promise实例
promise接收一个函数作为参数,该函数接收两个参数,他们是resolve,reject两个函数
(1)resolve函数用来将promise对象从未完成变成 成功 (pending状态变为fulfilled状态),在异步操作成功时调用,并将异步操作结果作为参数传递出去,同理
(2)reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
promise生成后可以使用then方法指定成功失败的回调函数
then方法接收两个函数作为参数,第二个参数可以不传,两个函数都可以将promise返回结果作为参数传进来
举一个简单例子
var b = new Promise(() => resolve(1));
b.then((value) => console.log(value)); //1
then函数第一个参数作为接收resolve方法返回的promise返回对象作为参数传给console.log打印出来
2.2promise对象新建后就会立即执行
promise在异步队列里面优先级比settimeout高,此知识点是js的微任务宏任务的内容
2.3promise原型对象上的then方法
就来说一下最常用的then方法吧
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法,第二个then方法就会等待这个promise对象的结果
2.4promise原型对象上的catch方法
2.5promise原型对象上的all方法
promise的all方法用来将多个promise实例包装成一个promise实例
const p = Promise.all([p1, p2, p3]);
p的状态又p1,p2,p3决定,分成两种情况
1.当p1,p2,p3都为fulfilled的时候,p的状态会变成fulfilled,此时p1,p2,p3的返回值会拼成一个数组返回给p的回调函数
2.当这三个有一个被rejected,p就变成rejected,此时第一个被rejected的值就会被返回给p的回调函数
注意,如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。下图是🌰
let p1 = new Promise((resolve, reject) => resolve(42))
let p2 = new Promise((resolve, reject) => reject(43))
let p3 = new Promise((resolve, reject) => resolve(44))
let p4 = Promise.all([p1, p2, p3])
let p5 = Promise.all([p1, p3])
p1.then(v=>console.log('p1 then: ' + v)) // p1 then: 42
p4.then(v=>console.log('p4 then: ' + v)) // Promise {<rejected>: 43}
p4.catch(v=>console.log('catch: ' + v)) // catch: 43 p2被拒绝,p4的拒绝处理函数立即调用,不会等p1和p3结束执行。但p1和p2仍然会执行。
p5.then(v=>{
console.log(Array.isArray(v)) // true
console.log(v) // [ 42, 44 ]
})
2.5promise原型对象上的race方法
有时面试会经常问的一个问题 promise.all和promise.race的区别
顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
race方法是只要有一个promise被解决,整个promise就被解决
let r1 = Promise.resolve('r41')
let r11 = Promise.reject('r41')
let r2 = new Promise((resolve, reject) =>{
resolve('r42')
})
let r3 = new Promise((resolve, reject) =>{
reject('rejcet43')
})
let r4 = Promise.race([r1, r2, r3])
r4.then(v=>console.log('r4: ' + v)) // r4: r41
let r5 = Promise.race([r2, r3])
r5.then(value => console.log('then:' + value)) // then:r42
r5.catch(value => console.log('catch:' + value)) // 不执行
let r6 = Promise.race([r11, r2, r3])
r6.then(v=>console.log('r6 then: ' + v))
r6.catch(v=>console.log('r6 catch: ' + v)) // r6 catch: r41
race和promise的区别在于:race是有一个promise被解决,整个promise就完成,无论其中一个是resolve还是reject。而all是其中一个被reject,则整个promise就停止,而resolve不会导致停止
2.6 为什么选择promise
以前的异步处理是用回调函数一层一层嵌套出来的结构,这样使开发者看起来很凌乱
step1(function(value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
promise采用then方法接收异步结果,很清晰的链式结构
Q.fcall(function() {
return2;
}).then(function(val){
console.log(val);
//...
}).then(function(){
//...
}).done();
三、async函数原理
3.1 async是Generator 函数的语法糖,就是将Generator 函数和自动执行器,包装在一个函数里
3.2 async用法
async函数会返回一个promise对象
(1) 一遇到await就会先返回,等到返回的异步操作执行完成,再执行之后的代码,await后面跟着的是一个promise代码执行情况如上代码
(2)也可通过then添加回调函数,异步promise的结果返回到then的参数里面,代码如下
async function test () {
return 'test async function'
}
test().then(
result => console.log(result)
)
// 输出结果
// test async function
(3)注意点:await后面是一个promise,可能会出现异步操作失败的情况,所以将await命令放在try catch中
try里面执行如果遇到undefind或其他问题,错误提示就会出现在catch中参数msg里面
fetchOrderList = async () => {
try {
const data = await api.getReplenishDetail({ orderId: this.props.param.orderId });
this.setState({
dataSource: ds.cloneWithRows(data),
total: data && data.length,
});
} catch (msg) {
toolTip.show(msg || '获取补货详情失败');
}
}
连载async踩坑记录篇😅:
不是33应该在22的前面吗??
其实原因是我还没理解第一次踩坑的那句话 async函数返回的也是一个promise对象,对!就是返回一个promise,所以promise是一个异步方法,里面的环境里,setstate是同步的