关于一次性插入大量数据(几十万)的异步写法

首先情况是这样的 因为我需要一次授权全部的用户 所以当用户量很大的话 前端响应时间会超时 所以这时候就需要异步响应

一开始 写controller接口
这个authAppUser其实就传一个appId而已

    @RequiresPermissions({"authorize/index:foreverAuth"})
    @Transactional(rollbackFor = Exception.class)
    @PostMapping(value = "/saveAllUserAuth")
    @ApiOperation(value = "保存应用用户授权(全部用户)" , notes="保存应用用户授权(全部用户)")
    @OperationLog(operateType = OperateLogConstant.TYPE_AUTH, content = "保存应用用户授权(全部用户)",
        moduleName = AuthAppUser.MODULE_NAME, menuName = AuthAppUser.MENU_NAME, modelClassName = AuthAppUser.ENTITY_NAME)
    public ResultResp saveAllUserAuth(@RequestBody @Validated AuthAppUser authAppUser){
        return authAppUserService.asyncAuthAllUser(authAppUser,getCurrentUser());
    }

新建异步任务类

public abstract class Task<T extends Serializable> implements Serializable {

    public static final String TASK_ID_PREFIX = "AsyncTask:taskId:";
    private static final int DEFAULT_FLUID_INTERVAL = 300;//默认进度更新流控
    private String taskId;
    private TaskProgress<T> progress = new TaskProgress<>();
    private ProgressListener<T> listener;
    private long lastProgressTime = 0;//最后一次更新进度的时间
    private long finishProgress = 0;//当前任务执行完成的总进度数

    /**
     * @Description: 初始化taskId
     */
    public Task() {
        this.taskId = new StringBuffer(TASK_ID_PREFIX).append(UUID.randomUUID().toString().replace("-", "")).
                append(":").append(new Date().getTime()).toString();
    }

    /**
     * @description: 自定义task
     * @param: taskId 必须保证唯一
     * @date: 2021/12/1 17:07
     */
    public Task(String taskId) {
        this.taskId = TASK_ID_PREFIX + taskId;
    }

    /**
     * @description: 自定义task
     * @param: taskId 必须保证唯一
     * @param: invalidTime 任务失效时间,单位分钟,如果不能为0,如果为0不生效走默认配置
     * @date: 2021/12/1 17:07
     */
    public Task(String taskId, long invalidTime) {
        this.taskId = TASK_ID_PREFIX + taskId;
        if (invalidTime > 0) {
            progress.setInvalidTime(invalidTime);
        }
    }

    public final String getTaskId() {
        return this.taskId;
    }

    public void setListener(ProgressListener<T> listener) {
        this.listener = listener;
    }

    /**
     * @Description: 进度更新
     * @Param fluidInterval 更新进度间隔时间
     */
    private void onProgress(int fluidInterval) {
        long t = lastProgressTime, t2 = System.currentTimeMillis();
        if (fluidInterval > 0) {
            if (t2 - t < fluidInterval) {
                return;
            }
        }
        if (this.finishProgress > 0) {
            this.progress.setProgress(this.finishProgress);
            this.finishProgress = 0;
        }
        lastProgressTime = t2;
        if (listener != null) {
            getPercentage(this.progress.getTotal(), this.progress.getProgress());
            listener.onProgress(getTaskId(), this.progress);
        }
    }

    /**
     * @Description: 计算任务进度百分比
     * @Param total
     * @Param progress
     */
    final private void getPercentage(long total, long progress) {
        if (total <= 0 || progress < 0 || total < progress) {
            return;
        }
        if (progress == 0) {
            this.progress.setPercentage(0);
            return;
        }
        double v = (double) progress / (double) total;
        String str = String.format("%.2f", v);
        double f1 = Double.parseDouble(str);
        this.progress.setPercentage((int) (f1 * 100));
    }

    /**
     * @Description: 更新任务为就绪状态
     */
    public void prepare() {
        progress.setStatus(TaskProgress.Status.PREPARE);
        progress.setStage("任务准备中");
        onProgress(0);
    }

    /**
     * @Description: 更新任务为失败状态
     * @Param message   错误信息
     */
    public void error(String message) {
        progress.setMessage(message);
        progress.setStatus(TaskProgress.Status.ERROR);
        progress.setStage("任务失败");
        onProgress(0);
    }

    /**
     * @Description: 更新任务为完成状态
     * @Param result 返回值
     */
    public void finish(T result) {
        progress.setStatus(TaskProgress.Status.FINISH);
        progress.setStage("任务结束");
        progress.setData(result);
        progress.setPercentage(100);
        onProgress(0);
    }

    /**
     * @Description: 更新进度阶段
     * @Param stage     任务处于哪个阶段(中文信息,可以为空)
     * @Param total     当前任务的总进度
     * @Param progress  当前进度
     * @Param message   进度描述信息(中文信息,可以为空)
     */
    final protected void progress(String stage, long total, long progress, String message) {
        if (StringUtils.isNotBlank(stage)) {
            this.progress.setStage(stage);
        }
        this.progress.setTotal(total);
        this.progress.setProgress(progress);
        if (StringUtils.isNotBlank(message)) {
            this.progress.setMessage(message);
        }
        onProgress(0);
    }

    /**
     * @Description: 更新进度阶段
     * @Param total     当前任务的总进度
     * @Param progress  当前进度
     * @Param message   进度描述信息(中文信息,可以为空)
     */
    final protected void progress(long total, long progress, String message) {
        this.progress("", total, progress, message);
    }

    /**
     * @Description: 设置当前进度
     * @Param total      当前任务的总进度
     * @Param progress   当前进度
     */
    final protected void progress(long total, long progress) {
        this.progress.setTotal(total);
        this.progress.setProgress(progress);
        onProgress(DEFAULT_FLUID_INTERVAL);
    }

    /**
     * @Description: 更新进度阶段
     * @Param progress   当前进度
     * @Param message    进度描述信息(中文信息,可以为空)
     */
    final protected void progress(long progress, String message) {
        this.progress.setProgress(progress);
        if (StringUtils.isNotBlank(message)) {
            this.progress.setMessage(message);
        }
        onProgress(DEFAULT_FLUID_INTERVAL);
    }

    /**
     * @Description: 更新进度阶段
     * @Param progress   当前进度
     */
    final protected void progress(long progress) {
        this.progress.setProgress(progress);
        onProgress(DEFAULT_FLUID_INTERVAL);
    }

    /**
     * @Description: 更新进度阶段
     * @Param message    进度描述信息(中文信息)
     */
    final protected void progress(String message) {
        this.progress.setMessage(message);
        onProgress(DEFAULT_FLUID_INTERVAL);
    }

    /**
     * @Description: 流控更新进度
     * @Param fluidInterval 刷新进度的毫秒数
     * @Param progress      当前进度
     * @Param message       进度描述信息(中文信息,可以为空)
     */
    final protected void progressFluid(int fluidInterval, long progress, String message) {
        this.progress.setProgress(progress);
        if (StringUtils.isNotBlank(message)) {
            this.progress.setMessage(message);
        }
        onProgress(fluidInterval);
    }

    final protected void progressFluid(Integer progress) {
        progressFluid(20, progress, null);
    }

    /**
     * @description:将任务运行过程中生成的文件Id存储到redis中
     * @param: fileId
     * @return: void
     * @author: ljixuan
     * @date: 2022/4/18 17:11
     */
    final protected void setFileId(String fileId) {
        this.progress.setFileId(fileId);
        onProgress(0);
    }

    /**
     * @description:设置当前完成的总进度数
     * @param: progress
     * @return: void
     * @author: ljixuan
     * @date: 2023/1/30 15:35
     */
    final protected void setFinishProgress(long progress) {
        if (progress < 0) {
            return;
        }
        this.finishProgress = progress;
    }

    /**
     * @Description: 异步任务执行开始
     */
    public T run() throws Exception {
        progress.setStatus(TaskProgress.Status.RUN);
        progress.setStage("任务运行中");
        onProgress(0);
        return doInBackground();
    }

    /**
     * @Description: 后台执行任务
     */
    protected abstract T doInBackground() throws Exception;

    /**
     * @Description: 任务取消后执行,如果开启事务,该方法在事务回滚后执行
     */
    public void afterCanceled() {
        //在子类实现
    }

    /**
     * @Description: 任务失败后执行,如果开启事务,该方法在事务回滚后执行
     */
    public void afterError() {
        //在子类实现
    }

    /**
     * @Description: 任务完成后执行,如果开启事务,该方法在事务提交后执行
     */
    public void afterFinish() {
        //在子类实现
    }
}

异步进度条类

public class TaskProgress<T extends Serializable> implements Serializable {

    public enum Status {
        PREPARE, RUN, FINISH, ERROR, CANCEL
    }

    private Status status; //任务状态
    private String stage; //任务处于哪个阶段(中文信息,可以为空)
    private long total = 0L; //total 为空或-1表示当前阶段无法计算进度
    private long progress = 0L;//当前进度
    private int percentage = 0;//当前进度百分比 total/progress 整数(0-100)
    private String message;//进度描述信息(中文信息,可以为空)
    private T data;//任务执行成功,要返回的内容
    private String fileId = "";//下载文件id(excel导入使用)

    private long invalidTime = 60;//任务存储到redis的失效时间,默认60,单位分钟

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public String getStage() {
        return stage;
    }

    public void setStage(String stage) {
        this.stage = stage;
    }

    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
    }

    public long getProgress() {
        return progress;
    }

    public void setProgress(long progress) {
        this.progress = progress;
    }

    public int getPercentage() {
        return percentage;
    }

    public void setPercentage(int percentage) {
        this.percentage = percentage;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public long getInvalidTime() {
        return invalidTime;
    }

    public void setInvalidTime(long invalidTime) {
        this.invalidTime = invalidTime;
    }

    public String getFileId() {
        return fileId;
    }

    public void setFileId(String fileId) {
        this.fileId = fileId;
    }

异步任务监听任务进度

public interface ProgressListener<T extends Serializable> extends Serializable {
    void onProgress(String taskId, TaskProgress<T> progress) throws CancellationException;
}

接下来 编写异步 工具类

方法编写

public interface IAsyncTaskService<T extends Serializable> extends Serializable {

    /**
     * @Description: 启动任务,会返回一个任务id,前端轮询去查看任务的状态
     * @Param task
     */
    ResultResp<String> exec(Task<T> task);

    /**
     * @Description: 启动任务,会返回一个任务id,前端轮询去查看任务的状态
     * @Param task
     * @Param enableTransaction 是否开启任务的事务,默认不开启
     */
    ResultResp<String> exec(Task<T> task, Boolean enableTransaction);

    /**
     * @Description: 获取进度条
     * @Param taskId
     */
    TaskProgress<?> getProgress(String taskId);

    /**
     * @Description: 取消任务
     * @Param taskId
     */
    Boolean cancel(String taskId);

    /**
     * @description: 获取任务的结果
     * @param: taskId
     * @return: com.linewell.idaas.model.ResultResp<com.linewell.idaas.service.asynctask.TaskProgress>
     */
    ResultResp<TaskProgress> getTaskResult(String taskId);

}

实现类编写

@Service
public class AsyncTaskServiceImpl implements IAsyncTaskService {
    public static final String TASK_PROGRESS_PREFIX = "asyncTask:";
    private static final Logger log = LoggerFactory.getLogger(AsyncTaskServiceImpl.class);
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Override
    public ResultResp<String> exec(Task task) {
        return exec(task, false);
    }

    @Override
    public ResultResp<String> exec(Task task, Boolean enableTransaction) {
        String id = task.getTaskId();
        if (hasSameTaskRunning(task)) {
            return ResultResp.error(CodeEnum.EXIT_INFO, "任务正在进行中!");
        }
        task.setListener(this::updateProgress);
        task.prepare();
        CompletableFuture.runAsync(() -> {
            TransactionStatus transaction = startTransaction(enableTransaction);
            try {
                task.finish(task.run());
                commitTransaction(enableTransaction, transaction);
            } catch (CancellationException e) {
                log.info("任务取消:taskId={}", task.getTaskId(), e);
                rollbackTransaction(enableTransaction, transaction);
                task.afterCanceled();
                deleteProgress(task.getTaskId());
            } catch (Exception e) {
                log.error("任务执行失败!,taskId={}", id, e);
                rollbackTransaction(enableTransaction, transaction);
                task.error(e.getMessage());
            } finally {
                System.gc();
            }
        }, AsyncThreadPoolConfig.getThreadPoolTaskExecutor());
        return ResultResp.success(id);
    }

    /**
     * @description: 手动开启事务
     * @param: enableTransaction
     * @return: org.springframework.transaction.TransactionStatus
     */
    private TransactionStatus startTransaction(Boolean enableTransaction) {
        if (BooleanUtil.isTrue(enableTransaction)) {
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务
            return dataSourceTransactionManager.getTransaction(def); // 获得事务状态
        }
        return null;
    }

    /**
     * @description: 提交事务
     * @param: enableTransaction
     * @param: transaction
     */
    private void commitTransaction(Boolean enableTransaction, TransactionStatus transaction) {
        if (BooleanUtil.isTrue(enableTransaction) && null != transaction) {
            dataSourceTransactionManager.commit(transaction);
        }
    }

    /**
     * @description: 回滚事务
     * @param: enableTransaction
     * @param: transaction
     */
    private void rollbackTransaction(Boolean enableTransaction, TransactionStatus transaction) {
        if (BooleanUtil.isTrue(enableTransaction) && null != transaction) {
            dataSourceTransactionManager.rollback(transaction);
        }
    }


    /**
     * @Description: 更新进度
     * @Param taskId
     * @Param progress
     */
    private void updateProgress(String taskId, TaskProgress<?> progress) {
        TaskProgress.Status status = progress.getStatus();
        if (!TaskProgress.Status.CANCEL.equals(status) && isCancel(taskId)) {
            throw new CancellationException("任务已取消");
        }
        if (TaskProgress.Status.FINISH.equals(status) || TaskProgress.Status.ERROR.equals(status)) {
            //任务结束 设置缓存时间1分钟
            redisTemplate.opsForValue().set(TASK_PROGRESS_PREFIX + taskId, progress, 1, TimeUnit.MINUTES);
        } else {
            //任务进行 设置缓存时间,默认1小时
            long invalidTime = progress.getInvalidTime();
            if (invalidTime <= 0) {
                invalidTime = 60;
            }
            redisTemplate.opsForValue().set(TASK_PROGRESS_PREFIX + taskId, progress, invalidTime, TimeUnit.MINUTES);
        }
    }


    @Override
    public TaskProgress<?> getProgress(String taskId) {
        return (TaskProgress<?>) redisTemplate.opsForValue().get(TASK_PROGRESS_PREFIX + taskId);
    }

    @Override
    public Boolean cancel(String taskId) {
        TaskProgress<?> progress = getProgress(taskId);
        if (null == progress) {
            return false;
        }
        TaskProgress.Status status = progress.getStatus();
        if (TaskProgress.Status.CANCEL.equals(status)) {
            return true;
        }
        //未完成且未报错的任务,手动取消任务
        if (!TaskProgress.Status.FINISH.equals(status) && !TaskProgress.Status.ERROR.equals(status)) {
            setCancelFlag(taskId);
            progress.setStatus(TaskProgress.Status.CANCEL);
            progress.setStage("任务取消");
            updateProgress(taskId, progress);
            return true;
        }
        return false;
    }

    @Override
    public ResultResp<TaskProgress> getTaskResult(String taskId) {
        while (true) {
            TaskProgress<?> progress = getProgress(taskId);
            if (null == progress) {
                return ResultResp.error(CodeEnum.NO_DATA);
            }
            TaskProgress.Status status = progress.getStatus();
            if (null == status) {
                return ResultResp.error(CodeEnum.NO_DATA);
            }
            if (TaskProgress.Status.ERROR.equals(status) || TaskProgress.Status.FINISH.equals(status) || TaskProgress.Status.CANCEL.equals(status)) {
                return ResultResp.success(progress);
            }
        }
    }

    /**
     * @Description: 判断任务是否已经取消
     * @Param taskId
     */
    private Boolean isCancel(String taskId) {
        return null != redisTemplate.opsForValue().get(TASK_PROGRESS_PREFIX + taskId + ":status");
    }

    /**
     * @Description: 查询是否有相同的任务在运行
     * @Param task
     */
    private boolean hasSameTaskRunning(Task<?> task) {
        TaskProgress<?> progress = getProgress(task.getTaskId());
        if (null == progress) {
            return false;
        }
        return true;
    }

    /**
     * @Description: 删除进度
     * @Param taskId
     */
    private void deleteProgress(String taskId) {
        redisTemplate.delete(TASK_PROGRESS_PREFIX + taskId);
        deleteCancelFlag(taskId);
    }

    /**
     * @Description: 设置任务取消标志
     * @Param taskId
     */
    private void setCancelFlag(String taskId) {
        redisTemplate.opsForValue().set(TASK_PROGRESS_PREFIX + taskId + ":status", "cancel", 1, TimeUnit.HOURS);
    }

    /**
     * @Description: 删除任务取消标志
     * @Param taskId
     */
    private void deleteCancelFlag(String taskId) {
        redisTemplate.delete(TASK_PROGRESS_PREFIX + taskId + ":status");
    }

}

authAppUserService.asyncAuthAllUser方法实现

@Override
    public ResultResp<String> asyncAuthAllUser(AuthAppUser authAppUser, User currentUser) {
        return asyncTaskService.exec(new Task() {
            @Override
            protected Serializable doInBackground() throws Exception {
                progressFluid(0,0,"授权准备中。。。");
                String curId = currentUser.getId();
                Page<AuthUserVo> page = new Page<>();
                int current = 1;
                long size = 100;
                page.setCurrent(current);
                page.setSize(size);
                IPage<AuthUserVo> authUserVoIPage;
                authUserVoIPage = authAppUserService.userAppPage(page, null, authAppUser.getAppId(), false, curId);
                long count = authUserVoIPage.getTotal() / 100 + 1;
                this.pageSaveAuthAppUser(authAppUser, curId, size, count);
                return "授权成功";
            }
            public void pageSaveAuthAppUser(AuthAppUser authAppUser, String curId, long size, long count) {
                Page<AuthUserVo> page = new Page<>();
                page.setSize(size);
                int current = 1;
                IPage<AuthUserVo> authUserVoIPage;
                long taskCount = 0L;
                while (true) {
                    page.setCurrent(current);
                    authUserVoIPage = authAppUserService.userAppPage(page, null, authAppUser.getAppId(), false, curId);
                    if (authUserVoIPage.getRecords().size() == 0) {
                        break;
                    }
                    progress("",authUserVoIPage.getTotal(),taskCount++,"");
                    List<String> userIds = authUserVoIPage.getRecords().stream().map(AuthUserVo::getId).collect(Collectors.toList());
                    asyncAuthAppForOrgAndUserService.authAuthAppUser(authAppUser, authAppUser.getAppId(), userIds, current, (int) count);
                }
            }
        }, true);
    }

asyncAuthAppForOrgAndUserService.authAuthAppUser

    public void authAuthAppUser(AuthAppUser authAppUser, String appId, List<String> userIds, Integer page, Integer count) {
        logger.info("开始执行按照应用授权所有用户:当前页={},总页数={}", page, count);
            //判断数据库中是否存在  没有话的再进行添加
            List<AuthAppUser> list = authAppUserService.getByUserIdList(userIds, appId);
            List<String> dbAuthUserIdList = list.stream().map(AuthAppUser::getUserId).collect(Collectors.toList());
            List<String> noExistsUserIdList = userIds.stream().filter(userId -> !dbAuthUserIdList.contains(userId)).collect(Collectors.toList());

            for (String uId : noExistsUserIdList) {
                AuthAppUser appUser = new AuthAppUser();
                appUser.setAppId(appId);
                appUser.setUserId(uId);
                if (ObjectUtil.isNotNull(authAppUser.getStartTime())) {
                    appUser.setStartTime(authAppUser.getStartTime());
                    appUser.setEndTime(authAppUser.getEndTime());
                }
                authAppUserService.save(appUser);
            }
    }

前端的话 我这里使用的vue 因为我想实现的是有进度条显示进度
所以在vue页面中写一个进度条组件

<!-- 使用方法:
     1. import TaskProgress from '@/components/task-progress'; 引入并注册组件
     2. <TaskProgress v-if="taskId" :taskid="taskId" title="XXXXX" content="XXXXX" :cancelable="false" @finish="finishTask" downloadable=true ></TaskProgress>   添加组件
     参数说明:
        1)taskid:通过调用后端接口,返回一个任务id,必传
        2)title:进度框显示的标题,非必传,有默认值
        3)cancelable:是否显示取消按钮,非必传,默认为true显示
        4)finish:任务执行成功后的回调方法
        5)content:进度条上方的详细说明,非必传,有默认值,或根据后端设置的内容显示
        6)downloadable:默认值为false,是否下载文件,任务结束返回值是文件id的才可使用
-->
<template>
  <el-dialog :show-close="false" :title="title" :visible="dialogVisible" width="30%">
    <span>{{contentInfo}}</span>
    <el-progress :percentage="currentProgress.percentage" :stroke-width="14"/>
     <span class="dialog-footer" slot="footer">
          <el-button @click="cancel" v-if="cancelable">取 消</el-button>
     </span>
  </el-dialog>
</template>

<script>
  import request from '@/utils/request'
  import {downloadFile} from "@/api/file";

  export default {
    props: {
      title: {//进度框显示的标题
        type: String,
        default: "任务进度"
      },
      content: {//进度条上方的详细说明
        type: String,
        default: "任务进行中,请稍等。。。"
      },
      cancelable: {//是否可取消,将显示取消按钮通知服务器取消任务
        type: Boolean,
        default: true
      },
      taskid: {//任务id
        type: String,
      },
      downloadable: {//是否下载文件,任务结束返回值是绝对路径的才可使用(可参考新版用户机构导出)
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        id: undefined,
        currentProgress: {
          stage: undefined,
          status: undefined,
          progress: undefined,
          total: undefined,
          message: undefined,
          percentage: undefined
        },
        interval: undefined,
        dialogVisible: false,
        contentInfo: this.content,
      };
    },
    computed: {},
    created() {
      if (this.taskid) {
        this.dialogVisible = true;
        this.startLoop(this.taskid);
      }
    },
    destroyed() {
      this.stopInterval();
    },
    watch: {
      taskid(id) {
        if (id && this.id != id) {
          this.currentProgress = {};
          this.contentInfo = "任务进行中,请稍等。。。";
          this.startLoop(id);
          this.dialogVisible = true;
        }
      }
    },
    methods: {
      startLoop(taskid) {
        this.id = taskid;
        this.interval = window.setInterval(() => {
          getTask(taskid).then(res => {
            if (res.data.status == true) {
              this.updateProgress(res.data.data);
            }
          }).catch(err => {
            this.dialogVisible = false;
            this.stopInterval();
          })
        }, 2000);//间隔2s轮询一次
      },
      updateProgress(p) {
        this.currentProgress = p;
        let status = this.currentProgress.status;
        if (p.message) {
          this.contentInfo = p.message;
        }
        if (p.percentage) {
          this.currentProgress.percentage = parseInt(p.percentage);
        }
        if (status == 'FINISH') {
          this.stopInterval();
          let result = this.currentProgress.data;
          if (this.downloadable == true && result != undefined && result != '') {
            this.download(result);
          }
          this.dialogVisible = false;
          this.$emit('finish', result);
        }
        if (status == 'CANCEL') {
          this.stopInterval();
          this.dialogVisible = false;
          this.$message.success('任务取消成功');
        }
        if (status == 'ERROR') {
          this.stopInterval();
          this.dialogVisible = false;
          let defaultMsg = '任务执行失败';
          if (this.currentProgress.message) {
            defaultMsg = defaultMsg + ":" + this.currentProgress.message;
          }
          this.$message.error(defaultMsg);
        }
      },
      stopInterval() {
        clearInterval(this.interval);
      },
      cancel() {
        this.stopInterval();
        this.dialogVisible = false;
        cancelTask(this.taskid).then(res => {
          if (res.data.status == true) {
            this.$message.success('任务取消成功');
          }
        });
      },
      download(url) {
        const a = document.createElement("a");
        a.href = downloadFile(url);
        a.click();
      }
    }
  };

  //根据任务id,获取当前任务的状态
  export function getTask(taskid) {
    return request({
      url: `/asynctask/progress?taskId=` + taskid,
      method: 'get',
    })
  }

  //根据任务id,取消任务
  export function cancelTask(taskid) {
    return request({
      url: `/asynctask/cancel?taskId=` + taskid,
      method: 'get',
    })
  }

</script>

在vue的list页面中引入这个组件

import TaskProgress from '@/components/task-progress';

放在合适的位置 这个taskIds是后端一直在刷新传过来的
放在合适的位置

授权方法中添加taskId

//永久授权所有用户
    foreverAuthAll() {
        this.$alert((
          <div class="el-message-box--custom-body">
            <div class="el-message-box--custom-label">确认授权所有用户?</div>
          </div>
        ), '', {
          type: 'warning',
          showCancelButton: true,
          confirmButtonText: '授权',
          customClass: 'el-message-box--nohead el-message-box--custom',
          callback: (action) => {
            if(action === 'confirm') {
              this.authUserAll = true;
              this.authInfo.type = 4;
              this.authInfo.userId = "-";
              this.disableButton();
              saveAuth(this.authInfo).then(res => {
                if (res.data.status) {
                  this.taskId = res.data.data; //这里添加taskId
                  this.authUserAll = false;
                }
              }).catch((error) => {
              this.authUserAll = false;
              this.$message({
                showClose: true,
                message: "后台正在进行授权操作,请稍后再进行操作",
                type: "error"
              });
            });
            }
          }
        });
    },

授权成功后 重新刷新页面
这个taskFinish是之前那个进度条组件中的方法

    taskFinish(res){
      const page = {
                    current: this.params.current,
                    size: this.params.size,
                    total: this.tableOption.page.total,
                  }
                  let selected = 0
                  switch(this.currentType) {
                    case 1: selected = this.authInfo.userId.split(','); break;
                    case 2: selected = this.authInfo.appId.split(','); break;
                    case 3: selected = this.authInfo.orgId.split(','); break;
                    case 4: selected = this.authInfo.appId.split(','); break;
                    case 5: selected = this.authInfo.appRoleId.split(','); break;
                  }
                  if (canGotoPrePage(this.tableData.length, selected.length, page)) {
                    this.params.current--
                  }
                   this.authUserAll = false;
                    this.authInfo.type = '';
                    this.getAuthOrg();
                   this.getList();
                   this.$message.success(res);
    },

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]中的代码是一个封装了AJAX函数的示例,用于请求10w条数据。该函数使用XMLHttpRequest对象发送GET请求,并通过Promise对象返回请求结果。引用\[2\]中提到,为了减少渲染的开销,可以每次只渲染10条数据,而不是一次性渲染10w条数据。这样可以避免卡顿的问题。引用\[3\]中的代码展示了一种分页渲染数据的方法,将10w条数据按照每页数量limit分成多页,利用setTimeout每次渲染一页数据,从而减少渲染时间。 对于Vue来说,如果一次性请求一万条数据,可能会导致页面卡顿或加载时间过长。为了提高性能和用户体验,可以考虑使用分页加载数据的方式。可以将数据分成多个页面,每次只请求当前页面的数据,然后根据需要进行切换和加载。这样可以避免一次性加载大量数据造成的性能问题。 另外,可以使用Vue的异步组件或者虚拟滚动等技术来优化大数据量的渲染。异步组件可以延迟加载组件,只在需要的时候才进行渲染,从而提高页面加载速度。虚拟滚动则是只渲染可见区域的数据,而不是全部渲染,从而减少渲染的开销。 总结起来,为了一次性请求一万条数据,可以考虑使用分页加载数据异步组件或虚拟滚动等技术来提高性能和用户体验。 #### 引用[.reference_title] - *1* *3* [后端一次给你10万条数据,如何优雅展示,到底考察我什么?](https://blog.csdn.net/muzidigbig/article/details/125925704)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [vue虚拟列表,一次性拿到10w条数据](https://blog.csdn.net/weixin_49554584/article/details/128504572)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值