本文探讨如何利用JavaScript的事件循环机制优化列表数据预加载。针对传统下拉加载中接口响应慢导致的Loading显示过长问题,提出在同步任务执行完毕后立即通过微任务或宏任务队列预请求下一页数据。文章结合小程序wx.nextTick与原生Promise实现方案,并分析高负载下任务积压及setTimeout自调用的优化思路。
背景
在开发列表页面时,通常采用分页加载策略,每页请求10条数据,用户滚动至底部时触发下一页请求。当前常见做法是在请求期间显示加载状态(loading)。然而,若后端接口响应缓慢,用户需长时间等待loading状态,影响交互体验。
什么是事件循环
可以将事件循环机制类比为餐馆运营:主线程如同主要工作台,微任务板紧邻工作台,宏任务板位于门边。
同步任务相当于直接点菜的顾客,主线程会立即处理其订单,即直接在主线程上执行。
微任务(快速便签板) :现在,假设顾客吃饭过程中,要求加一杯水。你告诉他们“稍等,我马上来”,然后迅速在微任务板上写下“送水”(微任务),然后继续处理当前排队的客户。处理完排队的客户转身就能看到并立刻执行快速便签板上的微任务。
宏任务如同预约外卖,记录在门边便签板上。这类任务优先级较低,需在当前所有同步任务及微任务执行完毕后,主线程才会去处理宏任务队列中的任务,如制作外卖或清理餐桌。
事件循环怎么和数据预加载关联起来
在获取第一页数据后,可将请求下一页数据的操作放入异步任务队列(微任务或宏任务)。这样,当当前同步任务执行完成后,主线程会立即从队列中取出任务执行,从而实现下一页数据的预加载。
实现
请求数据
// 从服务器请求数据
loadData(page) {
// '''''
return list
}
请求下一页,异步任务
- 小程序实现
//-------------------------页面初始化的时候---------------------------------------
this.setData({
list: await loadData(page)
})
// wx.nextTick创建异步任务,等待空闲后执行
wx.nextTick(async () => {
// 下一页数据先放在变量里面存起,等滑动到底部的时候将nextList追加到list,并且预请求再下一页
const nextList = await loadData(page + 1)
})
//-------------------------页面下滑到底部的时候---------------------------------------
this.setData({
list: [...this.data.list, ...nextList]
})
// wx.nextTick创建异步任务,等待空闲后执行
wx.nextTick(async () => {
// 下一页数据先放在变量里面存起,等滑动到底部的时候将nextList追加到list,并且预请求再下一页
const nextList = await loadData(page + 1)
})
- 非小程序实现
// 创建一个异步任务
MicroTasks(callback: () => {}) {
Promise.resolve().then(() => {
callback()
})
}
// 将上述wx.nextTick换成MicroTasks,其他不变
MicroTasks(async () => {
const nexList = await loadData(page + 1)
})
扩展
根据事件循环原理,异步任务必须等待所有同步任务执行完毕后方可执行。若到达异步任务执行时间点时同步任务仍未完成,异步任务将被推迟执行。
例如,使用setInterval(() => {}, 1000)设置每秒回调,回调任务会在1000毫秒后进入异步队列。若同步任务耗时过长,该异步任务会被延迟;若连续多个异步任务进入队列而前一个未执行,将导致任务积压。可通过setTimeout自调用缓解积压,但无法完全解决高负载下的延迟问题。
- setTimeout自调用例子
let timeoutId;
function customInterval(callback, delay) {
function execute() {
// 执行你的任务...
callback();
// 根据任务执行情况决定是否继续调用
if (/* 需要继续执行的条件 */) {
timeoutId = setTimeout(execute, delay);
}
}
// 立即开始第一次执行
execute();
}
// 使用示例
customInterval(() => {
console.log('执行中...');
// ...你的任务代码
}, 1000); // 延迟1000毫秒
// 如果需要停止循环,可以通过 clearTimeout(timeoutId); 来实现
到此这篇关于JavaScript利用事件循环实现数据预加载的文章就介绍到这了,更多相关JavaScript数据预加载内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!