很多人都知道JavaScript的闭包,也知道大致是一个什么意思,但是对于闭包的应用场合不是很清楚
最近在改造项目的过程之中修改前端接口轮训方式的时候用到了闭包驱动setTimeout来实现一个类似定时器的功能,可以开启定时器也可以关闭定时器
代码如下
// 创建异步轮训器(setTimeout实现),导出一个闭包对象,用于控制轮训 createLooper (func, time = 1000, params, callback = () => { }, err = () => { }) { // 轮训时钟 let timer = -1; // 轮训状态(开启,关闭) let status = true; // Promise化的setTimeout function setTimeoutPromise (func, time, params) { return new Promise((resolve, reject) => { timer = setTimeout(async () => { try { let result = await func(params); resolve(result); } catch (e) { reject(e); } }, time); }); } // 导出的用于控制轮训的闭包对象 const closureObj = { start () { if (!status) { asyncLoop(); status = true; } }, stop () { if (status) { clearTimeout(timer); status = false; } }, }; // 首次访问,不在轮训体之内的 async function firstCall () { try { let result = await func(params); callback(result, closureObj); return true; } catch (e) { clearTimeout(timer); status = false; console.error(e.message); err(e, closureObj); return false; } } // 异步轮训循环 async function asyncLoop () { let status = await firstCall(); if (status) { while (true) { try { let result = await setTimeoutPromise(func, time, params); callback(result, closureObj); } catch (e) { clearTimeout(timer); status = false; console.error(e.message); err(e, closureObj); } } } } asyncLoop(); return closureObj; },
这是一个函数,有五个参数
第一个参数为定时器要执行的函数
第二个参数为定时器的触发时间间隔
第三个参数为定时器执行参数的参数
第四个参数为获取执行函数返回值的回调
第五个参数为错误处理的回调
这个函数返回一个对象,这个对象内有两个方法都是闭包导出的方法
分别是start和stop,而这两个方法都访问了函数内部的status(轮训状态)变量以及timer(setTimeout返回的Id),所以可以控制定时器开启和关闭
正是因为闭包的能力所以我们可以调用这个函数返回的对象中的方法来控制函数内部的setTimeout的开启和关闭
这就是我在工作中遇到的闭包的一个小的应用场所