JavaScript利用事件循环实现数据预加载

当我们请求好第一页数据后,将请求下一页放到异步任务队列里(宏任务或者微任务),等当前同步任务执行完成后,立马请求下一页数据,本文给大家介绍了JavaScript如何利用事件循环实现数据预加载,需要的朋友可以参考下

背景

有一个从后端获取的数据列表,每页请求10条,每次下拉到底部的是时候请求下一页。目前做法是,请求下一页的时候底部显示loading,有个问题就是如果接口返回比较慢,loading则会显示的比较久

JavaScript利用事件循环实现数据预加载

什么是事件循环

假如你是一个餐馆老板,你有一个主要工作台(主线程)和两个不同的便签板,一个贴在工作台旁(微任务板),另一个挂在门边(宏任务板)。

同步任务:任何走进餐馆直接点菜的顾客,你立即处理他们的订单,相当于同步任务,直接在主线程上执行。

微任务(快速便签板) :现在,假设顾客吃饭过程中,要求加一杯水。你告诉他们“稍等,我马上来”,然后迅速在微任务板上写下“送水”(微任务),然后继续处理当前排队的客户。处理完排队的客户转身就能看到并立刻执行快速便签板上的微任务。

宏任务(门边便签板) :而对于预约外卖的顾客,你记录下来,贴在门边的宏任务板上,这些任务相对不那么紧急,你打算在完成当前所有桌面上的服务后,以及处理完微任务板上的所有小事后,再去查看并逐一完成。比如,制作外卖、清理餐桌等,这些任务耗时较长,不会立刻执行,但也不会忘记做。

事件循环怎么和数据预加载关联起来

当我们请求好第一页数据后,将请求下一页放到异步任务队列里(宏任务或者微任务),等当前同步任务执行完成后,立马请求下一页数据

实现

请求数据

// 从服务器请求数据
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毫秒后setInterval回调任务会被放入异步任务队列,如果同步任务还没执行完成,这个异步任务会被推迟,如果,又过了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); 来实现

 

声明:本站所有信息内容均由用户自行发表,该内容观点仅代表用户本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。Email:tellusa@foxmail.com

给TA打赏
共{{data.count}}人
人已打赏
JS教程

在uniapp中custombar的使用步骤

2024-5-16 23:11:17

JS教程

uni-app 滚动到指定位置的操作方法

2024-5-16 23:23:46

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
有新私信 私信列表
搜索