javascript异步编程总结

前言

由于js涉及dom交互,如果多线程会出现很复杂当线程同步问题,故js是单线程模式,单线程模式指执行代码当线程只有一个,故每次只能执行一个任务
单线程当优点为简单,安全,缺点为耗时任务会阻塞代码运行,出现白屏假死等影响体验的现象
故为了解决阻塞问题,js将任务的执行分为同步和异步两种模式

同步模式

指代码中任务依次执行,后一个任务必须等前一个任务执行完毕才会执行,任务等执行顺序与代码的编写顺序一致,大部分任务均为同步执行
当代码加载进来后,会由自执行函数包裹所有代码,按照从上倒下,先把第一行放到调用栈,当代码执行完毕,弹出代码,再执行下一行代码,知道都执行完毕

异步模式

不会等待任务执行完毕,才去执行下一任务,开启以后就会执行下一个任务,后续的处理逻辑会通过回调函数方式处理
在主线程外开辟新的线程,在不阻塞主线程代码大情况下,用于处理一些耗时或计算量大的任务,当异步结束后,把回调函数加入到消息队列中,等待事件循环的调用

EventLoop

事件循环会监听调用栈和队列,在调用栈空了后,事件循环会从队列中拿出第一个任务,放到调用栈中执行,执行完毕后,再拿出下一个任务,依次循环

消息队列

消息队列是存储待执行的异步回调函数,并供事件循环调用当场所,当异步代码触发回调函数时,会把此函数放在队列末尾,事件循环每次在队列当最前方取出函数去执行

宏任务与微任务

微任务有js的Promise和nodejs的process.nexttick等
宏任务有setTimeout,setInterval,js主代码等
宏任务和微任务是相对于异步代码的,在事件循环时,当微任务队列中存在任务,那么会先调用所有微任务,全部执行完毕,再去调用第一个宏任务,依次循环

异步模式执行步骤

console.log('begin')
setTimeout(function timer1 () {
  console.log('timer1')
}, 1800)
console.log('end')

上方简单的异步代码,首先加载完所有代码后,会把代码放入一个自执行函数并把第一行同步代码压入调用栈,执行完毕后打印begin,然后把定时器压入调用栈,会开启一个线程用于计时,然后推出,再把end打印压入调用栈,打印end,再推出,执行完毕,调用栈为空
当计时到1.8s时,会把定时器的回调函数放到消息队列,事件循环监听到队列变更后,在调用栈为空时,会把队列的第一个推入调用栈(如果此时有微任务,会执行完所有微任务再执行此操作),执行定时器的回调函数,打印timer1

Promise

异步编程的根基是回调函数,而传统的回调函数嵌套写法,很难维护与阅读,promise可以使异步编程更可维护与阅读

new Promise(function (resolve, reject) {
  // 同步执行此函数体
  setTimeout(() => resolve(1))
}).then((v) => {
  console.log(v); // 1
});
状态有fulFilled(成功,对应resolve,执行then的第一个参数),rejected(失败,对应rejected,执行catch回调或then的第二个参数)
Promise.all()

参数为Promise对象组成的数组,返回新的Promise,当数组中所有的Promise的状态均为fulFilled,执行then回调,参数为所有Promise的返回值组成的数组,此数组与传入数组一一对应,否则执行catch

Promise.race()

参数为Promise对象组成的数组,返回新的Promise,当数组中有一个任务结束,则直接按照该任务的状态返回

Promise.resolve()

快速把值转化为Promise对象,并执行then的第一个参数,如传入Promise对象,会直接返回

Promise.reject()

快速把值转化为Promise对象,并执行then的第二个参数,如传入Promise对象,会直接返回

Promise.finally()

参数为函数,返回值为Promise对象,不论成功或失败均会调用,并且所传函数调用时没有参数,会把当前Promise的成功或失败的值,传递给返回的新的Promise对象

Generator

使用*和yield关键字,当调用函数时,不会直接执行,而是会返回Generator对象,当调用对象当next方法时,才会执行,并且遇到yield关键字会停止执行,直到再次调用next方法

function * foo () {
    const res = yield 'foo';
	return res;
}
const generator = foo()
const result = generator.next(); // foo

因为每次均须手动调用next方法,所以需要一个执行器去自动执行所有next方法

function co (generator) {
  const g = generator()
  function handleResult (result) {
    if (result.done) return // 生成器函数结束
    result.value.then(data => {
      handleResult(g.next(data))
    }, error => {
      g.throw(error)
    })
  }
  handleResult(g.next())
}
co(foo)

async await

async await是generator的语法糖,可不用自己调用自己封装执行器,看起来更像同步代码

async function main () {
    const users = await ajax('/api/users.json')
    const posts = await ajax('/api/posts.json')
    const urls = await ajax('/api/urls.json')
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值