同步异步与async/await

  1. JS的微任务和宏任务

JS是单线程的语言,同一时间只能做一件事

执行流程:同步 =》事件循环【微任务、宏任务】

进入事件循环:请求、定时器、事件

for (var i = 0; i < 3; i++) {
    setTimeout(function () {
        console.log(i)
    }, 1000 * i)
}

微任务:promise.then是微任务,promise是同步

宏任务:setTimeout

宏任务执行前先执行所有微任务

  1. async/await

async function asyncFn(){
    console.log('2');
    // await 可以控制异步
    await new Promise(res=>{
        console.log('3');
    })
    // 等同 .then 代码
    console.log('5');
}
// 同步优先
console.log('1');
asyncFn();
console.log('4');

// 1 2 3 4
  1. 优雅使用async/await

function pretty(promise){
    // 中间层,参数错误有限
    return promise.then(res =>{
        return [ undefined , res ]
    })// 处理过以后fulfilled
    .catch(err => {
        return [ err , undefined ]
     })// 处理过以后fulfilled
}
async function run(){
    // js语法
    // try{
    //     var res = await req();
    //     console.log('执行成功了',res);
    // }catch(e){
    //     console.log('执行失败了->',e);
    // }finally{
     //    console.log('执行最后了');
    // }
    // console.log('此处使用res',res)
    let [err ,data] = await pretty(req());
    if(err) return console.log('err->',err);
    console.log('data->',data)
}

ps:除了事件本身中抛出异常,也可以从全局中记录捕获异常信息

window.addEventListener('unhandledrejection',(err)=>{
    err.preventDefault;
    console.log('err',err.reason)
})

4.解决foreach问题-> 重写foreach

foreach 与同步事件定时器使用中,定时器失效

arr.forEach(async (el,index,newArr)=>{
       await req(ele);
    })

覆盖forEach方法

Array.prototype.forEach = function(fn){
    //健壮性判断
    if(type fn !== 'function') throw new Error('必须传递参数');
    // 判断this是数组
    if(!Array.isArray(this)) throw new Error('this必须数组');
    for(let i = 0,len = this.length;i++){
        this[i]
        fn.call(this,this[i],i,JSON.parse(JSON.stringify(this)))
    }
}

如果数组里面含有函数需要添加深拷贝(安全性优化)

// 深拷贝算法
function deepClone(obj) {
    // 基本数据类型和null不需要处理
    if (typeof obj !== 'object' || !obj) {
        // undefined null && 0
        return obj;//不作处理
    }
    if (cachedMap.has(obj)) {
        return cachedMap.get(obj);
    }
    // 需要处理
    if (obj instanceof RegExp) {
        let tmp = new RegExp(obj);
        cachedMap.set(obj, tmp);
        return tmp
    } else if (obj instanceof Map) {
        let tmp = new Map();
        cachedMap.set(obj, tmp);
        obj.forEach((val, key) => {
            tmp.set(deepClone(key).deepClone(val))
        })
        return tmp;
    } else if (obj instanceof Set) {
        let tmp = new Set();
        cachedMap.set(obj, tmp);
        tmp.forEach(val => {
            tmp.add(deepClone(val))
        })
        return tmp;
    } else {
        let tmp = new obj.constructor();
        cachedMap.set(obj, tmp);
        for (let key in obj) {
            tmp[key] = deepClone(obj[key]);
        }
        return tmp;
    }
}

Array.prototype.forEach = function(fn){
    //健壮性判断
    if(type fn !== 'function') throw new Error('必须传递参数');
    // 判断this是数组
    if(!Array.isArray(this)) throw new Error('this必须数组');
    for(let i = 0,len = this.length;i++){
        this[i]
        fn.call(this,this[i],i,deepClone(this))
    }
}

你可能感兴趣的:(前端基础,javascript,前端,开发语言)