如何将SetTimeout和SetInterval变成承诺

If you’ve ever wanted to then or await JavaScript’s setTimeout or setInterval, functions, you’re not alone. I’ve had to use these methods a lot at work to deal with some…interesting…third party behavior, so I’ve finally become familiar with promisifying functions. setTimeout may be simple, and setInterval is a tad trickier, so make sure you understand promises.

如果您曾经想要then await JavaScript的setTimeoutsetInterval函数,那么您并不孤单。 我不得不在工作中大量使用这些方法来处理某些…… 有趣的……第三方行为,因此我终于熟悉了混杂函数。 setTimeout可能很简单,而setInterval则有点棘手,因此请确保您了解promises

TL:DR; 代码 (TL:DR; the code)

const sleep = async (ms) => {
return new Promise(resolve => setTimeout(resolve, ms));
}const asyncInterval = async (callback, ms, triesLeft = 5) => {
return new Promise((resolve, reject) => {
const interval = setInterval(async () => {
if (await callback()) {
resolve();
clearInterval(interval);
} else if (triesLeft <= 1) {
reject();
clearInterval(interval);
}
triesLeft--;
}, ms);
});
}

There it is, if you want to see why, check below! But if that’s all you need, glad I could help!

在那里,如果您想知道为什么,请检查以下内容! 但是,仅此而已,很高兴我能提供帮助!

如何使setTimeout合理化 (How to promisify setTimeout)

Take this code:

采取以下代码:

const foo = () => {
setTimeout(() => {
console.log('Callback based stuff');
console.log('yet another thing');
// lots more stuff
}, 2000);
}

The annoying thing about setTimeout is that everything has to go inside that callback function. It can get cumbersome if there’s a lot to do. But there’s no extra callback needed when we use await:

setTimeout的烦人之处在于,所有内容都必须放入该回调函数中。 如果要做的事情很多,可能会很麻烦。 但是当我们使用await时,不需要额外的回调:

const asyncFoo = async () => {
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log('nice');
console.log('way better');
}

What’s happening here? Well, as you know a Promise really just calls a resolve function or reject function after something happens. What we’re doing is creating a new Promise and instead of passing in a callback to setTimeout, we pass in resolve. That way, after the milliseconds pass, it is resolve that gets invoked, and our promise is triggered and resolved. We can then await it and do whatever we want. Easy peasy…but it can be even peas-ier.

这里发生了什么事? 好吧,正如您所知道的, Promise实际上只是在发生某些情况后才调用resolve函数或拒绝函数。 我们正在做的是创建一个新的Promise ,而不是将回调传递给setTimeout ,而是传递resolve 。 这样,经过毫秒后,将调用resolve ,触发并解决我们的承诺。 然后,我们可以await它并做我们想做的任何事情。 很容易,但是它甚至可以更加豌豆。

进行睡眠功能 (Making a sleep function)

People tend to want to use the setTimeout function like a pause button. Other languages have a sleep function to halt their program for a set amount of time. Let’s make one!

人们倾向于像暂停按钮一样使用setTimeout函数。 其他语言具有sleep功能,可将其程序暂停一定时间。 让我们做一个!

const sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms));
}const asyncFoo = async () => {
await sleep(2000);
console.log('look at this');
await sleep(1000);
console.log('getting fancy now');
}

This is a simple utility function that can really come in handy, especially if it’s used it more than once, since nesting setTimeout looks truly terrible.

这是一个简单的实用函数,真的非常有用,特别是如果多次使用它,因为嵌套setTimeout看起来确实很糟糕。

通知setInterval (Promisifying setInterval)

If you want setInterval to run forever, you’re in a pickle, but if you just want to use it to handle a few retries and then move on, it can work. To do it, we’re going to use the same resolve trick as before, but we’ll also add a max amount of tries. If we don’t get something by then, we’ll move on and use reject. We have to wrap our attempt task, a fake server check, into a function and it must return true or false:

如果要使setInterval永久运行,则您会处于泡菜状态,但是,如果只想使用它来处理几次重试,然后继续下去,它就可以工作。 为此,我们将使用与以前相同的resolve技巧,但我们还将添加最大尝试次数。 如果到那时还没有得到任何东西,我们将继续并使用reject 。 我们必须将尝试任务(伪造的服务器检查)包装到一个函数中,并且它必须返回true或false:

// task must return true or falseconst fakeServerCheck = async () => {
console.log('check...');
return Math.random() > 0.8;
}const asyncInterval = async (callback, ms, triesLeft = 5) => {
return new Promise((resolve, reject) => {
const interval = setInterval(async () => {
if (await callback()) {
resolve();
clearInterval(interval);
} else if (triesLeft <= 1) {
reject();
clearInterval(interval);
}
triesLeft--;
}, ms);
});
}const wrapper = async () => {
try {
await asyncInterval(fakeServerCheck, 500);
} catch (e) {
console.log('error handling');
}
console.log("Done!");
}wrapper();

The secret sauce here is that our task function returns a boolean. That way, we can know whether or not to move on. You’ll also notice I’m adding an await before callback even though fakeServerCheck is synchronous. That’s because in real life, that function will likely be doing something async, and I’m trying to make the asyncInterval function as cut and copy-able as possible.

这里的秘密之处在于我们的任务函数返回一个布尔值。 这样,我们可以知道是否继续前进。 您还会注意到,即使fakeServerCheck是同步的,我也在callback之前添加了一个await 。 那是因为在现实生活中,该函数可能会做async事情,而我正在尝试使asyncInterval函数尽可能地剪切和可复制。

现在一切都匹配了 (Now everything matches)

There you go! With these two functions, sleep and asyncInterval you don’t have the awkward mix of timed callbacks and regular promises. I know using these kinds of timers isn’t super common, but if you do find yourself using them, this should really help.

你去! 有了sleepasyncInterval这两个函数,您就不会在定时回调和常规promise的混合使用中感到尴尬。 我知道使用这种计时器并不常见,但是如果您发现自己正在使用它们,那应该会有所帮助。

happy coding everyone,

祝大家编码愉快,

mike

麦克风

翻译自: https://levelup.gitconnected.com/how-to-turn-settimeout-and-setinterval-into-promises-6a4977f0ace3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值