[utils]setTimeout结合递归调用实现前端轮询

163 阅读1分钟

需求背景

前端点击“生成”按钮后,需要实时查询当前状态,如果为“done”则进行下一步操作,否则一直处于loading状态。

无websocket服务,只能通过前端轮询实现。

实现

<script setup lang="ts">
    import { ref } from 'vue'
    import { fetchApiStatus } from '@/api/status' // 查询当前状态的接口

    async function getStatus() {  
        try {   
            const data = await fetchApiStatus({id: 'xxxxx'})    
            // 满足条件时,返回接口数据    
            if (data.status === 'done') {     
                return data    
            } else {
              // 不满足条件时,等待1秒钟,再继续执行下次查询   
               await sleep(1000)   
               return await getStatus() 
           } 
        } catch (e) { 
            // 网络异常、超时等错误也会返回,从而终止轮询。
            return e  
        }
    }

    // 使用setTimeout和Promise模拟休眠函数,使程序等待ms时间后再继续执行。
    function sleep(ms) {  return new Promise(resolve => setTimeout(resolve, ms))}

    // 开始轮询
    const loading = ref(false)
    async function handleStart() { 
        loading.value = true 
        const result = await getStatus() 
        loading.value = false
    }
</script>

<template> 
    <el-button :loading="loading" @click="handleStart">请求</el-button>
</template>

优点

不受网络快慢影响,保证在上一次请求完成之后,等待指定时间,再进行下次请求。