async和await
async
async&await是Promise和Generator的语法糖。
1.可以作用在任何方法前, 返回值是一个Promise对象(回调函数也可以使用async)
async function fn() { return "Hello" };
fn();
2.函数内部return的返回值, 会成为then回调函数的参数
var fn2 = async () => {
return 111
}
fn2().then(res=>{
console.log(res);
})
3.async作用的方法,如果内部出现报错,可以被promise的catch方法捕获。常规使用,一般都会通过try catch进行有可能报错的代码处理.
await
当 await 关键字与异步函数一起使用时,它的真正优势就变得明显了 —— 事实上, await 只在异步函数里面才起作用。它可以放在任何异步的,基于 promise 的函数之前。它会暂停代码在该行上,直到 promise 完成,然后返回结果值。在暂停的同时,其他正在等待执行的代码就有机会执行了。
您可以在调用任何返回Promise的函数时使用 await,包括Web API函数。
{
let p1 = ()=>{
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve("hello world")
},3000)
})
}
async function fn3(){
console.time("step3_1");
let res = await p1();
console.timeEnd("step3_1");
}
fn3();
}
1.await只能作用在async修饰的方法中,不能单独使用,如果使用报错:await is only valid in async functions and the top level bodies of modules
2.await是会阻塞代码执行。
{//promise
let p1 = ()=>{
return new Promise((resolve, reject)=>{
resolve("hello world");
})
}
function fn(){
p1().then((res)=>{
console.log("step1_1==>",res);
})
console.log("step1_2")
}
fn();
//step1_2
//step1_1 hello world
}
{
let p1 = ()=>{
// return Promise.resolve("hello world")
return Promise.reject("hello world")
}
async function fn1(){
//使用await之后 像是在写同步代码一样
//await是会阻塞代码执行
try{
let res = await p1();
console.log("step2_1",res);
console.log("step2_2")
}catch (err){
console.log("step2_err==>",err)
}
}
fn1();
//step2_1 hello world
//step2_2
}
{
let p1 = ()=>{
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve("hello world")
},3000)
})
}
async function fn3(){
console.time("step3_1");
let res = await p1();
console.timeEnd("step3_1");
}
fn3();
}
3.正常情况 await后面跟着一个Promise对象; 返回的是Promise对象的成功后结果; 如果是一个普通值,那么会直接返回这个值
4.reject的返回 await没有办法进行捕获(使用try catch进行捕获)
我们知道async await是同步的写法异步的编程,可以用来解决回调地狱,我们就简单的写一个吧
在使用JavaScript时,为了实现某些逻辑经常会写出层层嵌套的回调函数,如果嵌套过多,会极大影响代码可读性和逻辑,这种情况也被成为回调地狱。回调地狱 简单说,就是函数作为参数层层嵌套。
解决1 拆解 function 将各步拆解为单个的 function
解决2 通过 Promise 链式调用的方式
解决4 async / await
// function buildCatList(list, returnVal) {
// return new Promise(function (resolve, reject) {
// setTimeout(function (name) {
// var catList = list === '' ? name : list + ',' + name
// resolve(catList)
// }, 200, returnVal)
// })
// }
// function fn(list) {
// return list + ',' + 555
// }
// async function render() {
// var a = await buildCatList('','Panther')
// var b = await buildCatList(a, 'Jaguar')
// var c = await buildCatList(b, 'Lion')
// var d = await fn(c)
// console.log(d) // Panther,Jaguar,Lion,555
// }
// render()
// function hell(arg) {
// return new Promise((resolve, reject) => {
// setTimeout(()=>{
// var val
// if(!arg) val = '1'
// else val = arg
// resolve(arg + 1)
// },1000)
// })
// }
// function fn(arg) {
// return arg + ',' + 'end'
// }
// async function render() {
// var a = await hell('2')
// var b = await hell(a)
// var c = await hell(b)
// var d = await fn(c)
// console.log(d)
// }
// render()
添加错误处理
您可以将同步的 try…catch 结构和 async/await 一起使用 。
async function myFetch() {
try {
let response = await fetch('coffee.jpg');
let myBlob = await response.blob();
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
} catch(e) {
console.log(e);
}
}
myFetch();
catch() {} 代码块会接收一个错误对象 e ; 我们现在可以将其记录到控制台,它将向我们提供详细的错误消息,显示错误被抛出的代码中的位置。
如果你想使用我们上面展示的第二个(重构)代码版本,你最好继续混合方式并将 .catch() 块链接到 .then() 调用的末尾,就像这样:
async function myFetch() {
let response = await fetch('coffee.jpg');
return await response.blob();
}
myFetch().then((blob) => {
let objectURL = URL.createObjectURL(blob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
})
.catch((e) =>
console.log(e)
);
感谢各位的大驾光临,多有纰漏请海涵