异步编程:promise,async,await

1、什么是异步编程?

异步编程允许我们在执行一个长时间任务时,程序不需要等待,而是继续执行之后的代码,直到这些任务完成后再回来通知你 ,通常是以回调函数(callback)的形式,这种模式避免了的程序的堵塞,大大提高了cpu的执行效率。

 2、在JavaScript的两种实现异步的方式

2.1、第一种:回调函数

比如我们可以使用setTimeout()让一个函数在指定的时间后执行,这个函数本身会立刻返回,程序紧接着会执行之后的代码,而我们传入的回调函数则会等到预定的时间才会执行

setTimeout()=>{ //回调函数
console.log("灰太狼");
},3000);
console.log("你会立刻看到我");

2.1.1、回调函数的缺点

如果需要依次执行多个异步操作,整个程序会一层接着一层的嵌套下去,可读性会变得非常,这种情况也被叫做函数的回调地狱,为了解决这一问题,Promise应运而生

setTimeout()=>{ 
console.log("三秒后");
setTimeout()=>{ 
console.log("三秒后");
setTimeout()=>{ 
console.log("三秒后");

},3000);
},3000);
},3000);

2.2、第二种promise

JavaScript中使用Promise的API,fetch()就是一个很好的例子,它用来发起一个请求来获取服务器数据,可以用它动态的更新页面内容,也就是平时说的AJAX技术

这里调用fetch()去访问这个测试地址的数据  http://jsonplaceholder.typicode.com/posts

 可以看到fetch()立刻返回了一个Promise对象

 随后可以调用他的then方法并传递一个回调函数

fetch("http://jsonplaceholder.typicode.com/posts/1")
      //参数
.then((response)=>{//如果在未来成功完成,函数会被调起,请求的结果也会以参数的形式传递进来
});

2.2.2、Promise的优点

它可以用一种链式结构将多个异步操作串联起来

fetch("http://jsonplaceholder.typicode.com/posts/1")
.then((response)=>response.json())
//response.json也会返回一个Promise,
//他代表在未来的某一个时刻将返回的数据转换成JSON格式
.then((json)=>console.log(json));

如果我们想要等到他完成以后在执行其他操作,可以在她后面追加一个.then

 Promise的链式调用避免了代码的层层嵌套,即便有一个很长的链,代码也是向下增长,而并非向右,因此可读性会提升很多

fetch("http://...")
.then(...)
.then(...)
.then(...)
.then(...);

在过程中,会遇到很多错误,我们可以来捕获这些错误,可以附加一个catch,在链式结构的末尾

fetch("http://jsonplaceholder.typicode.com/posts/1")
.then((response)=>response.json())
.then((json)=>{
console.log(json);
})
.catch(error)=>{
console.error(error);
});

如果之前任意一个阶段发生了错误catch将会被触发then()将不会被执行

类似的Promise还提供finally方法,他会在Promise链结束之后调用,可以做一些清理工作

fetch("http://jsonplaceholder.typicode.com/posts/1")
.then((response)=>response.json())
.then((json)=>{
console.log(json);
})
.catch(error)=>{
console.error(error);
})
.finally(()=>{
//执行清理操作
});

如果用到了加载动画,可以在finally中关闭它

.finally(()=>{
stopLoadingAnimation();
})

3、async、await

首先我们需要使用async关键字将函数标记为异步函数

async function f(){
const response = await fetch("http://...");
//写了async,就不再需要then(),而是使用await语法
//await会等待Promise完成之后直接返回最终结果
const json = await response.json();
console.log(json);
}
f();

await虽然看上去会暂停其他函数的执行,但在等待的过程中JS同样可以处理其他任务,这是因为await的底层是基于Promise和循环事件机制实现的

3.1、await的使用陷阱

3.1.1、第一种

这样写不存在逻辑上的错误,但是会打破fetch()操作的并行

async function f(){
const a = await fetch("http://...");
const b = await fetch("http://...");

}
f();

正确做法,将所有的Promise用Promise.all组合起来

async function f(){
const promiseA = await fetch("http://...");
const promiseB = await fetch("http://...");
const [ a,b] = await Promise.all([promiseA,promiseB]);
}

3.2.2、第二种

如果想在异步中做执行的操作是不能直接调用forEach或者map这一类的方法的,应该用for循环

async fuction f(){
for (let i of[1,2,3]){
await someAsyncOperation();
}
console.log("done");
}]
f();

如果我们想要循环中的操作都并发执行,可以使用for await

async fuction f(){
const promise=[
somAsyncOperation(),
somAsyncOperation(),
somAsyncOperation(),
];
for await(let result of promises){
}
console.log("done");
}
f();

3.3.3、第三种

不可以在全局或者普通函数中使用await关键字,如果想在最外层使用await,可以先定义一个异步函数,再使用await

(async()=>{
await somAsyncOperation();
})();

一些旧版本的浏览器不支持await ,async语法,可以通过转译器编译成兼容的等效代码

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值