JS异步操作笔记整理

1. 单线程模型

JavaScript只在一个线程上运行,同时只能执行一个任务,其他任务都必须在后面排队等待。虽然允许JS创建多个线程,但子线程完全受主线程控制,且不得操作 DOM,所以并不影响JS单线程的本质。

2. 任务队列和事件循环

2.1 任务队列

JavaScript 运行时,除了一个正在运行的主线程,引擎还提供一个任务队列(task queue),里面是各种需要当前程序处理的异步任务。(可能存在多个任务队列)

2.2 执行流程

1. 执行所有同步任务。
2. 同步执行完后,检查任务队列里面的异步任务,如果满足条件,那么异步任务就重新进入主线程开始执行,这时它就变成同步任务了。
3. 等到执行完,下一个异步任务再进入主线程开始执行。一旦任务队列清空,程序就结束执行。

2.3 异步实现方法

异步任务的写法通常是回调函数。一旦异步任务重新进入主线程,就会执行对应的回调函数。如果一个异步任务没有回调函数,就不会进入任务队列,也就是说,不会重新进入主线程,因为没有用回调函数指定下一步的操作。

2.4 事件循环

JavaScript 引擎怎么知道异步任务有没有结果,能不能进入主线程呢?答案就是引擎在不停地检查,一遍又一遍,只要同步任务执行完了,引擎就会去检查那些挂起来的异步任务,是不是可以进入主线程了。

3. 异步操作的模式

function f1() {
  // ...
}

function f2() {
  // ...
}

f1();
f2();

如何才能让f1执行完在执行f2呢?解决方案是,改写f1,把f2写成f1的回调函数。

function f1(callback) {
  // ...
  callback();
}

function f2() {
  // ...
}

f1(f2);

4. 事件监听

采用事件驱动模式。异步任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
还是以f1和f2为例。首先,为f1绑定一个事件(这里采用的 jQuery 的写法)。

f1.on('done', f2);

上面这行代码的意思是,当f1发生done事件,就执行f2。然后,对f1进行改写:

function f1() {
  setTimeout(function () {
    // ...
    f1.trigger('done');
  }, 1000);
}

上面代码中,f1.trigger(‘done’)表示,执行完成后,立即触发done事件,从而开始执行f2。

4.3 发布/订阅(观察者模式)

事件完全可以理解成“信号”,如果存在一个“信号中心”,某个任务执行完成,就向信号中心“发布”(publish)一个信号,其他任务可以向信号中心“订阅”(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做”发布/订阅模式”

首先,f2向信号中心jQuery订阅done信号

jQuery.subscribe('done', f2);
// 对f1的改写
function f1() {
  setTimeout(function () {
    // ...
    jQuery.publish('done');
  }, 1000);
}

上面代码中,jQuery.publish(‘done’)的意思是,f1执行完成后,向信号中心jQuery发布done信号,从而引发f2的执行。

f2完成执行后,可以取消订阅(unsubscribe)

jQuery.unsubscribe('done', f2);

此方法类似于事件监听,但优于事件监听,可查看有多少信号和订阅者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值