js单线程
优势:任务队列简单
劣势:语句block,阻塞(表现为浏览器卡住)
由阻塞(同步执行)导致需要异步编程,代码块并不马上执行
异步操作场景
fs文件操作:
fs.readFile('./a.txt', 'utf-8', function(err, data)=>{
console.log(err? 'is Err' + err: 'data: '+ data)
})
事件操作
var btn = document.getElementById('btn')
btn.addEventListener('click', e=>{
console.log(e)
})
网络请求
$.ajax.get('http:127.0.0.1/users', function(data)=>{
// 网络请求数据处理
...
})
定时器
setTimeout(()=>{
// 延时任务处理
...
})
异步解决方案
1.事件
分类:dom事件;自定义事件;
特点:点对点
foo.on('finished', roo)
foo(){
setTimeout(()=>{
console.log('wait a little time')
foo.trigger('finished')
}, 900)
}
==>自定义事件,触发
// 创建时间
let event = new customEvent('myEvent', {
})
// 事件监听
document.addEventListener('myEvent', e=>{
console.log(e)
})
// 事件触发
document.dispatchEvent(event)
2.发布订阅与观察者模式
特点:群发,广播,以信号为中心,当异步事件完成,发出相应信号,所有该消息的订阅都会被通知
手写发布订阅
思路:维护订阅列表,on、off操作列表
class Pubsub{
constructor() {
this.handlers = {}
}
on(eventType, handle){
// 异常情况抛出,类型判断
if(!this.handlers.hasOwnProperty(eventType)){
this.handlers[eventType] = []
}
if(typeof handle === 'function'){
this.handlers[eventType].push(handle)
}else{
console.log('no handle function')
}
return this //返回对象本身 ,以支持链式调用
}
emit(eventType, ...args){
if(this.handlers.hasOwnProperty(eventType)){
this.handlers[eventType].forEach((item, key, arr) =>{
item.apply(null, args)
})
}else{
console.log('no handle func')
}
}
off(eventType, handle){
if(this.handlers.hasOwnProperty(eventType)){
}else{
console.log('no handle')
}
}
}
手写观察者
思路:拆分为两个角色(观察者-关注get、set、添加被观察者 ,被观察者-自身行为)
class Subject{ //观察者
constructor(){
this.state = ''
this.ob = []
}
attach(ob){
this.ob.push(ob)
}
getState(){
return this.state
}
setState(state){
this.state = state
this.ob.forEach(ob=>{
ob.update()
})
}
}
class Observer{
constructor(name, subject){
this.name = name
this.subject = sujbect
}
update(){
}
}
3.回调方式
特点:承前启后,耦合、回调地狱
function roo(){
console.log('run roor')
}
foo(callback){
setTimeout(()=>{
console.log('wait a little time')
callback()
}, 900)
}
foo(roo)
4.promise方式
then的方式实现链式调用,操作执行顺序
async、await
5.手写的步进器
特点:通过闭包实现
function takeStep(arr){
let index = 0
return {
next: function(){
return (
arr.length > index?{
value: arr[index++]
}: {
done: true
}
)
}
}
}
6.迭代器 方式的步进器
const iteatorer = arr => {
[Symbol.iterator](){
let index = 0
return {
next: function(){
return (
arr.length > index?{
value: arr[index++]
}: {
done: true
}
)
},
return(){
return {
done: true
}
}
}
}
}
for(let value of iteatorer([1,2,3,4])){
console.log(value)
if(value > 1){
break;
}
}
// generator-es6的步进
function *generator(){
yield 1;
yield 2;
}
let generator = generator()
generator.next() // {value: 1, done: false}
generator.next() // {value: 2, done: false}
ganerator.next() // {value: undefined, done: true}