在web端模拟简易版事件循环(eventLoop)

32 阅读1分钟

前置知识

  • Promise
  • 事件循环
  • 定时器
<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 100px;
            height: 100px;
            background-color: red;
            color: blue;
            transition: all 1s;
            line-height: 100px;
            text-align: center;
            cursor: pointer;
            user-select: none;
        }

        .box:hover {
            background-color: blue;
            color: red;
            transform: scale(.5);
        }
    </style>
</head>

<body>
    <div class="box">点击</div>
    <script>
        (async function (win) {
            function task() {
                return new Promise((resolve, reject) => {
                    win.request = resolve
                    win.rej = reject
                })
            }
            var events = new Map()
            async function eventLoop() {
                while (true) {
                    const { api: key, params } = await task();
                    if (events.has(key)) { // 精准触发
                        events.get(key)(params)
                    }
                }
            }
            win.addEvent = function (event) {
                events.set(event.key, event.event)
            }
             function testEvent(params) {
            console.log('请求此api次数为:' + params.count)
        }
        addEvent({ key: '/getUser', event: testEvent }) // 模拟服务端订阅了此事件
        eventLoop()
        })(window)
        const btn = document.querySelector('.box');
        let i = 0
        btn.addEventListener('click', () => {
            i++
            request({ api: '/getUser', params: { token: '123456', count: i } }) // 相当于发起api请求
        })
        // 模拟循环发起请求
        // for (let index = 0; index < 100000; index++) {
        //     setTimeout(() => { // 如果不走定时器异步则会导致只有一个微任务被添加到队列,因为当次Promise已结束
        //         request({ api: '/getUser', params: { token: '123456', count: index } }) // 相当于发起api请求
        //     }, 0);
        // }
    </script>
</body>

</html>