Skip to content

第十五章 异步

任务先后执行的问题

js为单线程语言

单线程问题是阻塞,按顺序执行即前边必须执行完。

解决的是执行顺序的问题。

js
function img(src){
	let img = new Img();
	img.src = src
}
img("iaklsjflk/zsdlkn/121sd");
console.log("alett");
可以知道,控制台输出会在图片加载之前就进行,产生报错。
js
主任务完成后,轮询任务队列。

加载与执行
loading&excusing
先加载不一定先执行。
先执行不一定先加载
js
定时器练习
setTimeOut()		单次执行
setInterval()		反复执行

任务排序

js
函数模块永远是在主进程加载完毕后执行。
主进程再慢也得等主进程加载完毕。
    function loading(src,resolve){
        let script = document.createElement("script");
        script.src = src;
        script.onload = resolve;
        document.body.appendChild(script);
    }
    loading("first.js",()=>{
        first();
    })
    loading("second.js",()=>{
        second();
    })
    console.log("main programs")
非主进程谁加载的快谁优先放入任务队列中,先进先出。
异步线程的数据可以使用主线程数据

任务请求

js
1、通过http模块请求后台数据
2、任务队列中添加任务
3、主程序执行任务,主程序执行完毕后执行任务队列中的任务
对于有文件依赖的任务,容易产生多层次回调嵌套。
产生了promise

promise

通知

js
Part1:准备阶段

new Promise((a,b)=>{}) //Promise{<pending>}  准备阶段
准备成功,用a函数通知;准备失败,用b函数通知。
js
Part2:处理阶段
~.then(a,b)
a,处理成功的回调;b,处理失败的回调
js
以微任务队列为主
如果微任务队列有任务,会优先执行微任务队列
Promise产出微任务队列。
微任务队列执行完毕后执行宏任务。

宏任务队列:
微任务队列:
	操作完毕后添加任务至微任务队列
	微任务队列进行排序
	微任务队列将排序好的任务放入放入主线程执行
    {
        new Promise((a, b) => {
            a("OK");
            b("No");
        }).then(a => {
            console.log("OK-OK")
        }, b => {
            console.log("No-No")
        })
    }

微任务与宏任务

js
当Promise执行到处理的时候(下方的resolve())会产生微任务。
微任务在下一次轮询时会执行。需要主线程执行完毕后执行
	let promise = new Promise(resolve=>{
        setTimeout(()=>{
            console.log("third-running");
            resolve();
        },100)
        console.log("first-running")
    }).then(next=>{
        console.log("fourth-running")
    })
    console.log("second-running")
微任务中的主线任务=>宏任务中的主线任务=>宏任务中的微任务=>微任务中的微任务

单一状态与状态中转

js
promise触发后状态不可逆
    let pro1 = new Promise((resolve, reject) => {
        setTimeout(()=>{
            reject("post2");
        },2000)
    })
    let pro2 = new Promise((resolve, reject) => {
        resolve(pro1);
    }).then(r => { console.log('right' + r) }, w => { console.log('wrong' + w) })

then

js
1、多个then如果未处理,会继续顺着向下找寻处理的then
2、单处理时,可设置null

    let promise = new Promise((a, b) => {
        b("request rejected");
    }).then().then(null, reason => {
        console.log(`Request error ${reason}`);
    })
js
Promise返回的也是个Promise
多个then连续时,会根据上一个处理是否存在来进行处理
    let p1 = new Promise((a, b) => {
        // a();
        b();
    })
    let p2 = p1.then(a => { console.log("right2") }, b => { console.log("error2") });
    let p3 = p2.then(a=>{console.log("right3")},b=>{console.log("error3")});
js
返回值是成对出现的
	
这样也是一个promise,是内部封装的promise
.then(value=>{return {then(resolve,reject){
	
	}
}})

其它类型promise封装

js
    let promise = new Promise((resolve, reject) => {
        resolve();
    }).then(run => {
        return class {
            static then(resolve, reject) {
                resolve("OK");
            }
        }
    }, stp => { console.log("stop in 2") }).then(value => {
        console.log(`${value} over`);
    })


catch接收

js
    new Promise((resolve,reject)=>{
        resolve();
    })
    .then(resolve2=>{return new Promise((new_resoleve,new_reject)=>{
        new_reject("new_reject err");
    })},reject2=>{console.log("2 is err")})
    .catch(err=>{console.log(`${err}cath error`)});

错误处理

js
    new Promise((resolve, reject) => {
        resolve("nope");
    })
        .then(value => {
            if (value != "yes") {
                return Promise.reject("no")//以上代码等同于throw new Error("no")
            }
        },null)
        .catch(value => {
            console.log(value + "---")
        })




自定义处理
class DIY_error extends Error{
        constructor(msg){
            super(msg);
            this.err_name = "address head error";
        }
    }
    function request(URL){
        let reg = /^https?/i;
        if(!reg.test(URL)){
            throw new DIY_error("address head error");
        }
    }

finally

js
无论陈工还是失败都会执行
用于发送完毕后关闭/结束某些功能

异步加载图片

js
    function loading_img(src){
        return new Promise((resolve,reject)=>{
            let image = new Image();
            image.src = src;
            image.onload = ()=>{resolve(image)};
            image.onerror = reject;
            document.body.appendChild(image);
        })
    }
    loading_img("./demo.png").then(image=>{
        image.style.border = "solid 2px black"
    })

定时器封装

js
    function timeout(delay = 1000) {
        return new Promise((resolve, reject) => {
            setTimeout(() => { resolve() }, delay);
        })
    }
    timeout(4000).then(re => {
        console.log("OK")
        return timeout(8000)
    })
        .then(a => { console.log("right") });

all接口

js
mesuare:
	Promise.all([p1,p2,p3...])
criteria:
	all are true is true
	全部返回的promise状态必须为已解决状态
    {
        const first = new Promise((resolve, reject) => {
            setTimeout(() => {
                reject("first is ok");
            }, 1000)
        }).catch(()=>{
            console.log("fitst is okk")
        })//catch 默认返回解决状态
        

        const second = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("second is ok")
            })
        })
        let all_promise = [first, second];
        Promise.all(all_promise).then(result => {
            console.log("全部成功");
        }).catch(() => {
            console.log("有至少一个不成功")
        })
    }

allSettled

js
都收集起来。 全部收起来之后再处理。
本身返回的值为成功状态

        let all_promises = [first, second];
        Promise.allSettled(all_promises).then(value => {
            let users = value.filter(user => {
                return user.status == "fulfiled";
            })
        })

race

js
接收多个promise,哪个快接收哪个
谁快用哪个,以快为准

Promise队列

js
    let res = Promise.resolve();
    res.then(value => {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log("1")
                resolve("errorL:value");
            }, 1000)
        })
    }).then(v=>{
        return new Promise(resolve=>{
            setTimeout(() => {
                console.log("2")
                resolve("ok");
            }, 1000);
        })
    })
上一个promise队列依赖下一个promise队列的改变
js
    function queue(num) {
        let promise = Promise.resolve();
        num.map(v => {
            promise = promise.then(_ => {
                return v();
            })
        })
    }
    function p1() {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log("p1")
                resolve();
            }, 1000);
        })
    }
    function p2() {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log("p2")
                resolve();
            }, 1000);
        })
    }
    queue([p1,p2]);
js
    function return_promise(num) {
        num.reduce((promise, n) => {
            return promise.then(() => {
                return new Promise(resolve => {
                    setTimeout(() => {
                        console.log(n)
                        resolve();
                    }, 1000)
                })
            })
        }, Promise.resolve())
    }
    return_promise([516, 516, 51, 651, 35])

async&awiat

js
async 相当于Promise
await 相当于 then
async---性质转化,如果function/class里需要先加载主进程,那么function/class需要进行async声明。
同样的,里边具体的执行代码块要用上 await方法。表示这个优先加载

class

js
 class user{
            constructor(name){
                this.name = name;
            }
            then(resolve,reject){
                let user = "yzh";
                resolve(user);
            }
        }
        async function usr(){
            let usr1 = await new user("yang");
            console.log(usr1)
        }
        usr() 


内部封装异步

class Demo {
        constructor(name) { this.name = name };
        async get() {
            let age = await new object();
            console.log
        }
    }

总结

js
    //普通函数生声明
    function ajax(name) {
        return `this is the data ${name}`
    }
    async function get() {
        return await ajax("my");
    }
    get().then(v => {
        console.log(v);
    })

    //对象调用
    function ajax(name) {
        return `this is the data ${name}`
    }
    let yzh = {
        async get(name) {
            return await ajax("object api");
        }
    }
    yzh.get().then(v=>{
        console.log(v)
    })

    //类封装
    function ajax(name) {
        return `this is the data ${name}`
    }
    class Usr {
        constructor() { };
        async get() {
            return await ajax("this is the method by Object");
        }
    }
    let yz = new Usr();
    yz.get().then(v => {
        console.log(v);
    })

错误处理

js
代码不应该只考虑正常,也要考虑异常
    //标准的Promise错误处理流程
    async function example() {
        try {
            let user = await "xxx";
            let lessons = await "xxx";
            return Data;
        } catch (args) {
            alert("error report")
        }
    };

对于函数类型,对象类型,类类型都可以使用.catch进行捕获

await并行处理

js
function new1_promise() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("new1_value");
            }, 1000)
        })
    }
    function new2_promise() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("new2_value");
            }, 1000)
        })
    }
    //fn1 并行处理
    async function yz() {
        let h1 = new1_promise();
        let h2 = new2_promise();
        let h1value = await h1;
        let h2value = await h2;
        console.log(h1value, h2value);
        setTimeout(() => {
            console.log(h1, h2);
        }, 2000)
    }
    yz()
    //fn2 all处理
    async function zh() {
        let res = await Promise.all([new1_promise(), new2_promise()]);
        console.log(res)
    }
    zh()