JS实现异步timeout

Promise已经作为JS的ES6标准,已经正式进入了浏览器环境和Node.js环境,但是对于程序员的需求来说,现在的Promise的功能还是有点不足的,比如说,我要设定一组Timeout该怎么做呢?

传统的同步方法实现起来很简单

let count = 10;
const func = () => {
    if(count > 0) {
        setTimeout(func, 1000);
        count -= 1;
    }
}
复制代码

这样我们就能实现10次,每次1秒的定时设定了,是不是很简单。

但是现在的问题是要用异步的方式来实现,那么继续使用原来的方法看看把

let count = 10;

const func = async () => {
    if(count > 0) {
        setTimeout(func, 1000);
        count -= 1;
    }
}
复制代码

唔...看起来似乎也没有问题,真的没有问题吗?请仔细的想想看func的类型,在同步方法中func的类型是Function,但是在异步方法中也是Function吗?NO!并不是,在异步方法中func的类型是Promise!OK,那么问题来了,既然func的类型是Promise那么你怎么可能用setTimeout(function, timeout)这个函数呢?你传递的类型都不多,结果自然是无法执行了!

那么有什么方法可以是实现异步的定时调用呢?毕竟有时候我们会需要一些网络传输的测试,当网络状况不良的时候,希望通过定时测试网络连接,获取网络状况,这里就要用到Promise.race()这个方法了,你或许说会文为什么不用bluebird库,里面也有实现的方法,这里我想提醒的是Promise.race()这个方法是目前在浏览器端和Node.js端中都是原生提供的方法,实现起来的移植性更高,那么现在我们来假想一个使用场景,现在我们需要连接远端的服务器,但是并不能保证100%的成功率,因此需要去ping一下服务器看看服务器是不是还活着

const axios = require('axios');

// 最大的连接重试次数
const MAX_RETRYS = 10
let count = 0;

/**
 * 测试服务器是不是还活着
 * @method {Function} resolve Promise的成功调用方法
 * @method {Function} reject Promise的失败调用方法
 */
const ping = async (resolve, reject) => {
    const response = axios.get(...);
    if(response.status === 200) {resolve();}
    else if(count > MAX_RETRYS) {reject();}
    
    count += 1;
}

// 以下是异步定时调用方法
// 每隔1秒重新ping一次
const tasks = [...Array(MAX_RETRYS + 1).keys()].map(i => {
    return new Promise((resolve,reject) => {
        setTimeout(ping(resolve, reject), i * 1000)
    })
})

// 处理ping通的
tasks.race().then(() => {.../*成功的后续执行*/})
.catch(() => {.../*失败的后续执行*/})
复制代码

这里我使用的方法是通过产生一组任务来模拟时间间隔,可以这么理解,我在时刻0的时候去ping一下,时刻1秒的时候去ping一下,时刻2秒的时候去ping一下,以此类推产生一组ping的任务,当时刻到的时候才去执行,效果跟同步的方法差不多,但是有一个与同步方法特别的不同的地方,就是这个任务队列不能是无穷大的,因此要设定一个最大尝试次数,其实实际应用时我们也会设置这么一个限制值,总不可能用户等一个小时连接服务器吧

对了这里解释下[...Array(MAX_RETRYS+1).keys()]的代码含义,这个方法类似于python中的range()函数,但是Javascript没有原生的实现方法,因此这里使用了ES6的新特性,简单的模拟了range()函数,具体含义大家看官方文档吧,很简单的

希望我的这个方法对你有帮助

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值