异步
异步概念
有很多场景存在。
setTimeout
会放到代码结束之后执行。
异步不会阻塞后面程序执行
单线程
var a = true
setTimeout(function(){a=false},100)
while(true){console.log('x')}
因为js是单线程的,进入while之后会死循环,没有线程去跑定时器。
异步的场景
- 定时器。setTimeout setInterval
- 网络请求
- promise
- async/await
定时器
settimeout0 不是马上执行,是单线程的js忙完了其他逻辑才运行,是异步的
可以考虑 requestAnimationFrame
这个函数自带节流 16.6ms
promise
除了Promise,同一时期的计算机科学家还使用了“终局”(eventual)、“期许”(future)、“延迟”(delay)和“迟付”(deferred)等术语指代同样的概念。所有这些概念描述的都是一种异步程序执行的机制。
经过一段时间的发展,最终规定了 Promses/A+
规范,也称为了 ES6 规范实现的范本。
api
Proimse
本身是引用类型,可以通过 new 来实例化。参数传入执行器。
实例状态机:
- pending 待定,进行中
- fulfilled/resolved/settled 解决、兑现
rejected 拒绝
pending 本身不一定非得变为另一个状态,但变到另外一个状态,不可再改变。
- pending 的过程本身是私有的,不能被修改,不能检测。
实例打印
构造函数打印
在谈论具体api时候,我们假想存在下面的函数:
class Promise{
then(){}
catch(){}
finally(){}
static all(){} // 一组Promise全部解决之后再解决
static allSettled(){} //
static race(){} // 一组Promise中最先出结果的无论是res还是rej的
static reject(){}
static resolve(){}
}
EventLoop
浏览器中的 eventloop
js遇到异步函数,会放到task里,等到当前执行队列空,开始执行task。
本质上,异步还是同步演变。
task分为两种:
- 微观任务micro task 称为 job
- 宏观任务 marco task 称为 task
console.log('script start') // 1
async function async1() {
await async2()// 去下一个 让出来
console.log('async1 end')//7
}
async function async2() {
console.log('async2 end')//2
}
async1()
setTimeout(function() {
console.log('setTimeout')//9
}, 0)
new Promise(resolve => {
console.log('Promise') //3
resolve()
})
.then(function() {
console.log('promise1')//5
})
.then(function() {
console.log('promise2')//6
})
console.log('script end') //4
观察这段代码。1-4 5-9
1-2牢记promise await是回调。
2-3-4 顺序执行 promise
然后继续执行 promise的回调 5-6
7 promise任务结束,继续回调
9 settimeout
总结:
- 先执行同步代码,这是宏观任务。
- 同步代码结束,当前执行队列空,看异步代码
- 执行微观任务
- 渲染页面
- 执行完微观任务,回到宏观任务执行settimeout等
所以,promise和 setTimeout 比,promise是微观任务先执行
微观任务 process.nextTick
promise
MutationObserver
宏观任务 script
setTimeout
setInterval
setImmediate
I/O
UI Rendering
node中的 event loop
和浏览器完全不同
node分为六个阶段,反复执行
timers — pending callbacks — idle,prepare — poll — check — close callbacks
timer
执行 setTimeout
setInterval
I/O
处理上一轮循环中少数未执行的I/O 回调
poll
- 回调timer阶段
- 执行 io 回调
慢慢看吧。
- 高阶函数,异步问题
- 发布订阅、观察者模式
- Promise应用
- 实现
- 面试题
- 扩展
- generator和co库
- async/await
高阶函数
这个函数式高阶函数
- 一个函数的参数是一个函数,比如回调函数
- 一个函数返回一个函数
应用场景
扩展业务代码。
假设我们有一个代码想要拓展
// 默认参数
function say(){console.log('say')}
// 补充before方法
Function.prototype.before = function(cb){
return ()=>{
cb()
this()
}
}
let beforeSay = say.before(()=>console.log('before say'))
beforeSay()
发布订阅 观察者
如果你看过 vue2 的源码,对下面的东西你会感兴趣
发布
let event = {
arr:[],
on(fn){this.arr.push(fn)},
emit(){
this.arr.forEach(fn=>fn())
}
}
我们维护了一个数组,先订阅,再发布
观察者模式
观察者和被观察者,被观察者发生变化需要通知。
也需要收集和通知。存在关联
// 小宝宝
class Subject {
constructor(name){
this.name = name
this.state = 'happy'
this.observers = [] // 观察者
}
setState(state){
this.state = state
// 调用观察者的方法
this.observers.forEach(o=>o.update(this))
}
attach(o){
this.observers.push(o) // 订阅
}
}
var baby = new Subject('name')
class Observer{
constructor(name){
this.name=name
}
update(instance){
// 在这里就拿到了观察者的实例
}
} // 父母
var father = new Observer('father')
var mother = new Observer('mother')
baby.attach(father)
baby.attach(mother)
baby.stetState('cry')
和vue太像了,以后用来举例子。
Promise/A+ 标准被社区支持。Promise 是一种状态机,只会是三种方式的一种。
-1 参考链接
- 高级程序设计 第四版