为了账号安全,请及时绑定邮箱和手机立即绑定

【备战春招】第3天 破解JavaScript高级玩法 第十讲

标签:
JavaScript

课程章节: 爱上异步编程

主讲老师: Cloud

课程内容:

今天学习的内容包括:

现代异步编程的核心:Promise

课程收获:

10.1 心得:

回调函数:

function login(callback) {
    setTimeout(() => {
        callback("token");
    }, 3000);
}


function getOrderId(token,callback) {
    if(token){
        setTimeout(() => {
            callback("orderId");
        }, 2000);
    }
}

function orderDetails(orderId,callback) {
    if(orderId){
        setTimeout(() => {
            callback("淘宝订单:购买xxx书一本");
        }, 1500);
    }
}



login((token) => {
    getOrderId(token,(orderId) => {
        orderDetails(orderId,(orderInfo) => {
            console.log(orderInfo);
        });
    });
});

回调函数异常:


function login(callback) {
    setTimeout(() => {
        callback("token");
    }, 2);
}


function getOrderId(token,callback) {
    if(token){
        setTimeout(() => {
            callback("orderId");
        }, 3);
    }
}

function orderDetails(orderId,callback) {
    if(orderId){
        setTimeout(() => {
            callback("淘宝订单:购买xxx书一本");
        }, 2);
    }


}


try{
    login((token) => {
        throw new Error("orderList");
        getOrderId(token,(orderId) => {
            orderDetails(orderId,(orderInfo) => {
                console.log(orderInfo);
            });
        });
    });
}catch(e){
    console.log("try catch error:",e);
}

简版延迟函数:

/**
 * 
 * 
 * @param {any} fn 需要延迟的方法
 * @param {any} delay 延迟时间
 * @param {any} context 上下文
 * @returns 
 */
function delay(fn, delay, context) {
    let defaultDelay = delay || 5000;
    let ticket;
    return {
        run(...args) {
            ticket = setTimeout(async () => {
                fn.apply(context, args);
            }, defaultDelay)
        },
        cancel: () => {
            clearTimeout(ticket);
        }
    }
}


const { run, cancel } = delay(() => { console.log("111") }, 3000);

run();

setTimeout(() => {
    cancel();
}, 1000);

延迟函数:


function isFunction(fn) {
    return typeof fn === 'function' || fn instanceof Function
}


/**
 * 
 * 
 * @param {any} fn 需要延迟的方法
 * @param {any} delay 延迟时间
 * @param {any} context 上下文
 * @returns 
 */
function delay(fn, delay, context) {
    let defaultDelay = delay || 5000;
    if (!isFunction(fn)) {
        return {
            run: () => Promise.resolve(),
            cancel: noop
        }
    }
    let ticket;
    let executed = false;
    return {
        run(...args) {
            return new Promise((resolve, reject) => {
                if (executed === true) {
                    return;
                }
                executed = true;
                ticket = setTimeout(async () => {
                    try {
                        const res = await fn.apply(context, args);
                        resolve(res);
                    } catch (err) {
                        reject(err)
                    } finally {
                        clearTimeout(ticket);
                    }
                }, defaultDelay)
            })
        },
        cancel: () => {
            clearTimeout(ticket);
        }
    }
}




//测试

const { run, cancel } = delay(() => { return "函数执行结果" }, 3000);

run().then((result) => {
    console.log("result:", result);
})

run().then(() => {
    console.log("多次调用run result:", result);
});


重试多次:

function isFunction(fn) {
    return typeof fn === 'function' || fn instanceof Function
}

function retry(fun, count, assert = () => false) {
    if (!isFunction(fun)) {
        return Promise.resolve();
    }
    return new Promise(async (resolve, reject) => {
        let error = null; //错误值
        for (let tryCount = 1; tryCount <= count; tryCount++) {
            try {
                const value = await fun(tryCount);
                if (assert(value, tryCount)) {
                    return resolve(value);
                }
            } catch (e) {
                error = e;
            }
        }
        reject(new Error("多次尝试失败"))
    });

}


// retry(()=>{
//     throw new Error("错误")
// },3).catch((e)=>{
//     console.log("捕获到错误:",e)
// });

let index = 0;

function createPromise(tryCount) {
    console.log("尝试次数:", tryCount)
    return new Promise((resolve, reject) => {
        index++;
        setTimeout(() => { resolve(index) }, 1000)
    })
}

retry(createPromise, 10, (res) => {
    return res == 5
}).then((res) => {
    console.log("当前的数据:", res);
}).catch((e) => {
    console.log("捕获到错误:", e)
});

EventEmitter:

import { BaseAsyncMessager, BaseReqData, GlobalReqOptions } from "../src/index";
import EventEmitter from "events";

const emitter = new EventEmitter();

interface RequestData extends BaseReqData {
    method: string;
    data?: any;
}
type ResponseData = RequestData;


// 初始化异步Messager
const emitterAsyncMessager = new BaseAsyncMessager<RequestData>({
    subscribe(onMessage) {
        console.log("emitterAsyncMessager: subscribe");
        emitter.on("message", onMessage as any);
        return () => {
            emitter.off("message", onMessage  as any);
        }
    },
    getReqCategory(data: RequestData) {
        console.log("emitterAsyncMessager: getReqCategory: method", data.method);
        return data.method;
    },
    getResCategory(data: ResponseData) {
        return data.method;
    },
    request(data: RequestData, key?: string) {
        emitter.emit("message-request", data);
    }
});


/* 模拟emitter另外一端 */ 

// 传统的事件通知
setInterval(() => {
    emitter.emit('message', {
        method: 'continuous-event',
        data: new Date().toLocaleTimeString()
    })
}, 3000)

// 监听 message-request 事件,然后回发事件
emitter.on("message-request", (data: RequestData) => {
    setTimeout(() => {
        emitter.emit("message", {
            method: data.method,
            data: `${data.method}--- data`
        })
    }, 3000)
})



/*使用方 */

// 调用
emitterAsyncMessager.invoke({
    method: "cccc",
    data: 111
}).then(res => console.log("res:", res))

// 传统的监听事件
emitterAsyncMessager.addHandler("continuous-event", function onEvent(data) {
    console.log("continuous-event:", data);
})

iframe:

    <iframe class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./iframe1.html" id="ifr"></iframe>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="../../dist/asyncMessager.js"></script>
    <script>

        function sendMessage(msg) {
            iframe1.contentWindow.postMessage(msg)
        }
        const iframe1 = document.getElementById("ifr");

        const asyncMessager = new AsyncMessager.BaseAsyncMessager({
            // logUnhandledEvent: false,
            subscribe(onMessage) {
                function onIframeMessage(msg) {
                    onMessage(msg.data);
                }
                window.addEventListener("message", onIframeMessage);
                return () => {
                    window.removeEventListener("message", onIframeMessage);
                }
            },
            getReqCategory(data) {
                console.log("asyncMessager getReqCategory: method", data.method);
                return data.method;
            },
            getResCategory(data) {
                return data.method;
            },
            request(data, key) {
                sendMessage(data);
            }
        });

        iframe1.contentWindow.onload = () => {
            asyncMessager.invoke({
                method: "init",
                data: {
                    user: 123456,
                    token: "blabla......"
                }
            }).then(res => console.log("index.html:", res, res))
        }
        asyncMessager.addHandler("timeInfo", function(data){
            console.log("index.html:timeInfo", data);
        })


    </script>

socket.io:

const socket = io("http://localhost:3000");

function sendMessage(msg) {
    socket.emit("message", msg)
}

const asyncMessager = new AsyncMessager.BaseAsyncMessager({
    // logUnhandledEvent: false,
    subscribe(onMessage) {
        function onSocketMessage(msg) {
            onMessage(msg);
        }
        socket.on("message", onSocketMessage);
        return () => {
            socket.off("message", onSocketMessage);
        }
    },    
    request(data, key) {
        sendMessage(data);
    }
});

socket.on("connect", () => {
    console.log("connect")
    asyncMessager.invoke({
        method: "getUsers",
        data: {
            user: 123456,
            token: "blabla......"
        }
    }).then(res => console.log("index.html:", res, res))
});

asyncMessager.addHandler("timeInfo", function (data) {
    console.log("index.html:timeInfo", data);
});

图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消