async/await 和 promise 的用法
参考:https://www.jianshu.com/p/ffa5cbe9ab29
promise
Promise构造函数的参数是一个函数,函数里面的代码是异步的,即Promise里面的操作,和Promise()外面的操作时异步"同时"进行的。Promise中的函数的第一个参数是回调函数,resolve用来触发then里面的代码,第二个参数是回调函数,reject用来触发catch中的代码,throw new Error();也可以触发catch,
resolve和reject是两个回调函数,调用resolve会触发then,reject会触发catch
<script>
new Promise((resolve, reject) =>{
setTimeout(() =>{
//成功的时候调用resolve
resolve('成功data')
//失败的时候调用reject
reject('error message')
}, 1000)
}).then((data) =>{
//处理成功后的逻辑
console.log(data);//这个data 是接收的resolve参数--
}).catch((err) =>{
console.log(err);
})
</script>
async/await ”vs“ promise
写法:
Promise
主要用then函数的链式调用,一直点点点,是一种从左向右的横向写法。 async/await
从上到下,顺序执行,就像写同步代码一样。这更符合人编写代码的习惯
参数数量
Promise
的then函数只能传递一个参数,虽然可以通过包装成对象,但是这会导致传递冗余信息,频繁的解析又重新组合参数,比较麻烦。 async/await
没有这个限制,就当做普通的局部变量来处理好了,用let或者const定义的块级变量,想怎么用就怎么用,想定义几个就定义几个,完全没有限制,也没有冗余的工作。
机制
Promise
是根据函数式编程的范式,对异步过程进行了一层封装。 async/await
是基于协程的机制,是真正的“保存上下文,控制权切换 ... ... 控制权恢复,取回上下文”这种机制,是对异步过程更精确的一种描述。
async/await
async/await
是基于Promise
的,是进一步的一种优化。不过再写代码的时候,Promise
本身的API出现得很少,很接近同步代码的写法。
async
只是表明里面可能有异步过程,里面可以有await
关键字,如果没有async
函数本身会马上返回,不会阻塞当前线程。它的函数的返回值是一个Promise
对象。
当return new Promise();
则直接处理promise对象
当return data;
则相当于Promise.resolve(data);
还是一个Promise
对象
两者都需要用用.then(data => { })
函数处理。
await
的是resolve(data)
消息,并把数据data
返回。比如,下面代码中,当Promise
对象由Pending
变为Resolved
的时候,变量a
就等于data
;然后再顺序执行下面的语句`console.log(a);
const a = await new Promise((resolve, reject) => {
// async process ...
return resolve(data);
});
console.log(a);
await
等待的虽然是promise
对象,但不必写.then(..)
,直接可以得到返回值。
通过await
标记的方法,只有该方法执行完成之后才能往后执行
async function asyncFunction() {
console.time('asyncFunction total executing:');
const sleep1 = await sleep(2000);
console.log('sleep1: ' + sleep1);
const [sleep2, sleep3, sleep4]= await Promise.all([sleep(2000), sleep(1000), sleep(1500)]);
console.log('sleep2: ' + sleep2);
console.log('sleep3: ' + sleep3);
console.log('sleep4: ' + sleep4);
const sleepRace = await Promise.race([sleep(3000), sleep(1000), sleep(1000)]);
console.log('sleep race: ' + sleepRace);
console.timeEnd('asyncFunction total executing:');
return 'asyncFunction done.' // 这个可以不返回,这里只是做个标记,为了显示流程
}
sleep1: sleep for 2000 ms
这是第一个await
之后的第一个异步过程,后面的代码,不论是同步和异步,都在等他执行完毕。-
sleep2 ~ sleep4
这是第二个await
之后的Promise.all()
异步过程。这是“比慢模式”,三个sleep
都完成后,再运行下面的代码s,耗时最长的是2000ms
; -
sleep race: sleep for 1000 ms
这是第三个await
之后的Promise.race()
异步过程。这是“比快模式”,耗时最短sleep
都完成后,就运行下面的代码。耗时最短的是1000ms
; -
asyncFunction total executing:: 5006.276123046875ms
这是最后的统计总共运行时间代码。三个await之后的异步过程之和
异常捕获
对于异常的捕获,除了传统的try/catch
async getData() {
try {
this.formInfos = await getFormInfos();
} catch (e) {
Toast(`数据获取失败,请稍后重试`)
}
}
也可以通过.catch去捕获异常
let books = await bookModel.fetchAll()
.catch((error) => { console.log(error); });
结合之后使用
const responseJson = await Promise.race([
fetch(url, requestConfig),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
])
.then((resPromise) => {
let resultPromise = resPromise.json()
return resultPromise
}).then((result) => {
return result
}).catch((e)=>{
throw new Error("网络出现问题~")
})
if (responseJson['success']) {
return responseJson['obj']
} else {
throw new Error(responseJson['msg'])
}
注意:
-
await
只能放在async
函数内部使用,不能放在普通函数里面,否则会报错。 -
后面放
Promise
对象,在Pending
状态时,相应的协程会交出控制权,进入等待状态。这个是本质。 -
await
后面也可以跟同步代码,不过系统会自动转化成一个Promise
对象。 比如const a = await 'hello world';
其实就相当于const a = await Promise.resolve('hello world');
-
await
只关心异步过程成功的消息resolve(data)
,拿到相应的数据data
。至于失败消息reject(error)
,不关心(可以放在一个try...catch
结构中统一处理)
Promise
promise代表非阻塞异步执行的抽象,所谓的非阻塞异步执行就是,promise执行的时候,其他程序可以继续往下执行,不必像await一样,需要等待。
console.log('Starting Execution');
const promise = rp('http://example.com/');
promise.then(result => console.log(result));
console.log("Can't know if promise has finished yet...");
正确的使用方式
// 错误示范
async getBooksAndAuthor(authorId) {
const books = await bookModel.fetchAll();
const author = await authorModel.fetch(authorId);
return {
author,
books: books.filter(book => book.authorId === authorId),
};
}
// 这里await之后就会阻塞,执行完一个执行下一个
// 正确姿势
async getBooksAndAuthor(authorId) {
const bookPromise = bookModel.fetchAll();
const authorPromise = authorModel.fetch(authorId);
const book = await bookPromise;
const author = await authorPromise;
return {
author,
books: books.filter(book => book.authorId === authorId),
};
}
// promise会异步执行,的带结果之后执行await