Skip to content

Commit

Permalink
udpate: 异步任务举例
Browse files Browse the repository at this point in the history
  • Loading branch information
qianguyihao committed May 26, 2021
1 parent a85287e commit 07102a7
Showing 1 changed file with 45 additions and 9 deletions.
54 changes: 45 additions & 9 deletions 05-JavaScript基础:异步编程和Ajax/01-单线程和异步.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ setTimeout(() => {

比如说,网络图片的请求,就是一个异步任务。前端如果同时请求多张网络网络图片,谁先请求完成就让谁先显示出来。

假如网络图片的请求做成同步任务,那就会出大问题,所有图片都得排队加载,如果第一张图片未加载完成,就得卡在那里,造成阻塞,导致其他图片都加载不出来。这肯定是不能接受的。
假如网络图片的请求做成同步任务,那就会出大问题,所有图片都得排队加载,如果第一张图片未加载完成,就得卡在那里,造成阻塞,导致其他图片都加载不出来。页面看上去也会很卡顿,这肯定是不能接受的。

### 前端使用异步的场景

什么时候需要**等待**,就什么时候用异步。

- 定时任务:setTimeout(定时炸弹)、setInterval(循环执行)
- 定时器:setTimeout(定时炸弹)、setInterval(循环执行)

- 事件绑定(比如说,按钮绑定点击事件之后,用户爱点不点。我们不可能卡在按钮那里,什么都不做。所以,应该用异步)

Expand All @@ -59,7 +59,7 @@ js 中常见的接口调用方式,有以下几种:
- Fetch
- axios

下一篇文章,我们重点讲一下接口调用里的 Ajax,然后在ES6语法中学习 **Promise**。在这之前,我们需要先了解同步任务、异步任务的事件循环机制。
下一篇文章,我们重点讲一下接口调用里的 Ajax,然后在 ES6 语法中学习 **Promise**。在这之前,我们需要先了解同步任务、异步任务的事件循环机制。

### 多次异步调用的顺序

Expand All @@ -79,7 +79,8 @@ js 中常见的接口调用方式,有以下几种:

- 当主线程的任务执行完毕之后,此时主线程处于空闲状态,于是会去读取 Event Queue 中的任务队列,如果有任务,则进入到主线程去执行。

## 代码示例

## 定时器:代码示例

掌握了上面的事件循环原理之后,我们来看几个例子。

Expand Down Expand Up @@ -144,8 +145,7 @@ setTimeout(() => {
sleep(5000); //表示很耗时的同步任务
```

上面的代码中,异步任务不是2秒之后执行,而是等耗时的同步任务执行完毕之后,才执行。那这个异步任务,是在5秒后执行?还是在7秒后执行?这个作业,留给读者你来思考~

上面的代码中,异步任务不是 2 秒之后执行,而是等耗时的同步任务执行完毕之后,才执行。那这个异步任务,是在 5 秒后执行?还是在 7 秒后执行?这个作业,留给读者你来思考~

### 举例 3(较真系列)

Expand All @@ -157,13 +157,49 @@ setTimeout(() => {

上面的代码中,等到 1 秒之后,真的会执行异步任务吗?其实不是。

在浏览器中, setTimeout()/ setInterval() 的每调用一次定时器的最小时间间隔是**4ms**,这通常是由于函数嵌套导致(嵌套层级达到一定深度),或者是由于已经执行的setInterval的回调函数阻塞导致的。
在浏览器中, setTimeout()/ setInterval() 的每调用一次定时器的最小时间间隔是**4ms**,这通常是由于函数嵌套导致(嵌套层级达到一定深度),或者是由于已经执行的 setInterval 的回调函数阻塞导致的。

上面的案例中,异步任务需要等待 1004 毫秒之后,才会从 Event Table 进入到 Event Queue。这在面试中也经常被问到。

## 异步任务举例
### 例1:加载图片

```js
// 加载图片的异步任务
function loadImage(file, success, fail) {
const img = new Image();
img.src = file;
img.onload = () => {
// 图片加载成功
success(img);
};
img.onerror = () => {
// 图片加载失败
fail(new Error('img load fail'));
};
}
loadImage(
'images/qia nguyihao.png',
(img) => {
console.log('图片加载成功');
document.body.appendChild(img);
img.style.border = 'solid 2px red';
},
(error) => {
console.log('图片加载失败');
console.log(error);
}
);
```


### 例2:定时器计时


上面的案例中,异步任务需要等待1004毫秒之后,才会从 Event Table 进入到 Event Queue。这在面试中也经常被问到。

## 参考链接

- [JS-同步任务,异步任务,微任务,和宏任务](https://github.com/PleaseStartYourPerformance/javaScript/issues/34)
- [JS 同步异步宏任务微任务](https://juejin.cn/post/6875605533127081992)[JavaScript 中事件循环的理解](https://zhuanlan.zhihu.com/p/364475433)[javascript 事件循环机制](https://github.com/reng99/blogs/issues/34)
- [如何实现比 setTimeout 80 倍的定时器?](https://mp.weixin.qq.com/s/NqzWkeOhqAU85XPkJu_wCA)

0 comments on commit 07102a7

Please sign in to comment.