async/await 的递归 setTimeout
Recursive setTimeout with async/await
我是 运行 一个递归的 setTimeout,所以我只想每分钟调用一次 API。
这是我的代码:
;(async function ticker (minutes) {
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
console.log({ dominance })
} catch (ex) {
console.log(ex.message)
} finally {
setTimeout(ticker, minutes * 60 * 1000)
}
})(1)
问题是:
- 当我启动服务器时,它会立即调用 API
- 第二次调用需要一分钟(预期行为)
- 第二次调用后,它开始按顺序调用 API,没有超时
它会立即调用它,因为您的代码就是这样做的。它立即执行 ticker(1)
函数调用。
当您从 setTimeout(ticker, ...)
调用 ticker 时,您没有将 minutes
参数传递给该函数 - 这就是 setTimeout()
没有正确延迟的原因。
如果您不希望它立即执行,则去掉 IIFE 并以 setTimeout()
开始它。然后,当您从 setTimeout()
回调中调用 ticker()
时,请务必将 minutes
参数传递给它,方法是将第三个参数传递给 setTimeout()
或创建一个它的回调函数很少。
这是一种实现方式:
async function ticker(minutes) {
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
console.log({ dominance })
} catch (ex) {
console.log(ex.message)
} finally {
setTimeout(ticker, minutes * 60 * 1000, minutes);
}
}
setTimeout(ticker, minutes * 60 * 1000, 1);
也许您只需要使用一些日程管理器,例如 bree
?
根据您的代码
- 这里不需要 IIFE。只需调用
setTimeout(() => ticker(1), minutes * 60 * 1000)
- 同样更改内部
setTimeout
调用以传递 minutes
参数,因为现在您只需传递 undefined
。这意味着 immediately
对应 setTimeout
.
ticker
期望minutes
作为参数,因此在setTimeout
中调用它时必须传递分钟。除此之外,setTimeout
期望在第一个参数中有一个函数,所以我建议简单地传递一个调用你的 ticker
函数的箭头函数。请检查以下代码:
;(async function ticker (minutes) {
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
console.log({ dominance })
} catch (ex) {
console.log(ex.message)
} finally {
setTimeout(() => ticker(minutes), minutes * 60 * 1000)
}
})(1)
我认为已经解决了问题。为了便于阅读,我建议您使用功能较少的方法:
;(async function ticker (minutes) {
while(true) {
await new Promise(res => setTimeout(res, minutes * 60 * 1000));
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
console.log({ dominance })
} catch (ex) {
console.log(ex.message)
}
}
})(1)
这是一个过于复杂且可能不适合的解决方案,setInterval
。我只是想展示我们如何使用 setInterval
来实现相同的行为。
const fetch = require('isomorphic-fetch')
const url = 'https://jsonplaceholder.typicode.com/posts';
const closeThis = () => {
let ids = [];
async function executeThisShiz(minutes) {
ids.forEach((id) => {
clearInterval(id);
})
try {
let res = await fetch(url);
res = await res.json();
console.log('yay')
return res;
} catch(e) {
// maybe abort the timer idk?
console.log('error', e);
} finally {
id = setInterval(() => {
executeThisShiz(minutes);
}, minutes*60*1000);
ids.push(id);
}
}
return {
ids,
executeThisShiz
}
}
const {executeThisShiz} = closeThis();
executeThisShiz(0.1);
这里已经有一些很好的解释,但我将稍微重构代码以利用 async/await 而无需外部库。
首先,让setTimeout
成为一个异步函数:
async function sleep(ms) {
return new Promise(res => setTimeout(res, ms));
}
接下来,让我们用它代替 setTimeout
:
(async function ticker (minutes) {
do {
await sleep(minutes * 60 * 1000);
await loadData();
} while (true);
async function loadData() {
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
} catch (err) {
console.error(ex.message);
}
}
})(1)
除了
,这几乎是一样的
- 服务器启动后等待一分钟
- 请求之间总是等待一分钟
它也更容易理解和阅读,并且由于您使用 async/await,它坚持单一范例(而不是使用 async/await 和 setTimeout
的回调) .
我是 运行 一个递归的 setTimeout,所以我只想每分钟调用一次 API。
这是我的代码:
;(async function ticker (minutes) {
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
console.log({ dominance })
} catch (ex) {
console.log(ex.message)
} finally {
setTimeout(ticker, minutes * 60 * 1000)
}
})(1)
问题是:
- 当我启动服务器时,它会立即调用 API
- 第二次调用需要一分钟(预期行为)
- 第二次调用后,它开始按顺序调用 API,没有超时
它会立即调用它,因为您的代码就是这样做的。它立即执行 ticker(1)
函数调用。
当您从 setTimeout(ticker, ...)
调用 ticker 时,您没有将 minutes
参数传递给该函数 - 这就是 setTimeout()
没有正确延迟的原因。
如果您不希望它立即执行,则去掉 IIFE 并以 setTimeout()
开始它。然后,当您从 setTimeout()
回调中调用 ticker()
时,请务必将 minutes
参数传递给它,方法是将第三个参数传递给 setTimeout()
或创建一个它的回调函数很少。
这是一种实现方式:
async function ticker(minutes) {
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
console.log({ dominance })
} catch (ex) {
console.log(ex.message)
} finally {
setTimeout(ticker, minutes * 60 * 1000, minutes);
}
}
setTimeout(ticker, minutes * 60 * 1000, 1);
也许您只需要使用一些日程管理器,例如 bree
?
根据您的代码
- 这里不需要 IIFE。只需调用
setTimeout(() => ticker(1), minutes * 60 * 1000)
- 同样更改内部
setTimeout
调用以传递minutes
参数,因为现在您只需传递undefined
。这意味着immediately
对应setTimeout
.
ticker
期望minutes
作为参数,因此在setTimeout
中调用它时必须传递分钟。除此之外,setTimeout
期望在第一个参数中有一个函数,所以我建议简单地传递一个调用你的 ticker
函数的箭头函数。请检查以下代码:
;(async function ticker (minutes) {
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
console.log({ dominance })
} catch (ex) {
console.log(ex.message)
} finally {
setTimeout(() => ticker(minutes), minutes * 60 * 1000)
}
})(1)
我认为
;(async function ticker (minutes) {
while(true) {
await new Promise(res => setTimeout(res, minutes * 60 * 1000));
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
console.log({ dominance })
} catch (ex) {
console.log(ex.message)
}
}
})(1)
这是一个过于复杂且可能不适合的解决方案,setInterval
。我只是想展示我们如何使用 setInterval
来实现相同的行为。
const fetch = require('isomorphic-fetch')
const url = 'https://jsonplaceholder.typicode.com/posts';
const closeThis = () => {
let ids = [];
async function executeThisShiz(minutes) {
ids.forEach((id) => {
clearInterval(id);
})
try {
let res = await fetch(url);
res = await res.json();
console.log('yay')
return res;
} catch(e) {
// maybe abort the timer idk?
console.log('error', e);
} finally {
id = setInterval(() => {
executeThisShiz(minutes);
}, minutes*60*1000);
ids.push(id);
}
}
return {
ids,
executeThisShiz
}
}
const {executeThisShiz} = closeThis();
executeThisShiz(0.1);
这里已经有一些很好的解释,但我将稍微重构代码以利用 async/await 而无需外部库。
首先,让setTimeout
成为一个异步函数:
async function sleep(ms) {
return new Promise(res => setTimeout(res, ms));
}
接下来,让我们用它代替 setTimeout
:
(async function ticker (minutes) {
do {
await sleep(minutes * 60 * 1000);
await loadData();
} while (true);
async function loadData() {
try {
const res = await coingecko.global()
const { market_cap_percentage } = res.data.data
dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth }
} catch (err) {
console.error(ex.message);
}
}
})(1)
除了
,这几乎是一样的- 服务器启动后等待一分钟
- 请求之间总是等待一分钟
它也更容易理解和阅读,并且由于您使用 async/await,它坚持单一范例(而不是使用 async/await 和 setTimeout
的回调) .