我正在开发一个 LED 条动画工具,它允许用户选择可以同时运行的多种效果。每个效果都是一个( Bluebird ) promise 。有一个 run()
方法可以设置 LED 灯带的颜色。
所有 Promise 使用 delay
方法以固定的 FPS 运行。
run(mode) {
return this.setStripColor(this.color).delay(1 / this.fps).then(() => { this.run(1 / this.fps) })
}
// example of an effect
rainbowSweep() {
// ..
// magical unicorn code
// ..
return Promise.resolve().delay(1 / this.fps).then(() => {
this.rainbowSweep()
})
app.rainbowSweep()
app.run()
是否可以使用某种数据结构来打开和关闭递归 promise ?换句话说,我如何向效果(递归 promise )发出停止递归的信号?
我正在考虑一个包含所有 promise 的数组。
但是当递归 promise 不再存在于数组中时,我不知道如何打破/解决它。我可以在返回
之前检查一下 promise 本身是否在数组内,但我希望有一种更优雅的方法。
最佳答案
让我们看一个简单的递归函数,它在较高层次上表达我们的程序
let RUNNING =
true
const main = async (elem, color = Color ()) =>
RUNNING
? delay (color, FPS)
.then (effect (color => setElemColor (elem, color)))
.then (color => main (elem, stepColor (color)))
: color
我们对Color
做了一点如意算盘。 , stepColor
,和setElemColor
(除其他外),让我们首先实现这些
const Color = (r = 128, g = 128, b = 128) =>
({ r, g, b })
const stepColor = ({ r, g, b }, step = 8) =>
b < 255
? Color (r, g, b + step)
: g < 255
? Color (r, g + step, 0)
: r < 255
? Color (r + step, 0, 0)
: Color (0, 0, 0)
const setElemColor = (elem, { r, g, b }) =>
elem.style.backgroundColor = `rgb(${r}, ${g}, ${b})`
const c = new Color () // { r: 128, g: 128, b: 128 }
setpColor (c) // { r: 128, g: 128, b: 136 }
现在我们有一种方法来创建颜色,获取“下一个”颜色,并且我们可以设置 HTML 元素的颜色
最后,我们编写助手 delay
和effect
。 delay
将创建一个解析为 ms
的 Promised 值毫秒。 effect
用于具有副作用的函数(例如设置 HTML 元素的属性)。和FPS
只是我们的每秒帧数常数
const delay = (x, ms) =>
new Promise (r => setTimeout (r, ms, x))
const effect = f => x =>
(f (x), x)
const FPS =
1000 / 30
要运行该程序,只需调用 main
带有输入元素。因为它是一个异步程序,所以不要忘记处理成功和错误情况。当程序最终停止时,将输出最后使用的颜色。
main (document.querySelector('#main'))
.then (console.log, console.error)
// => { Color r: 136, g: 8, b: 40 }
要停止程序,只需设置 RUNNING = false
随时
// stop after 5 seconds
setTimeout (() => RUNNING = false, 5000)
这是一个工作演示
const Color = (r = 128, g = 128, b = 128) =>
({ r, g, b })
const stepColor = ({ r, g, b }, step = 16) =>
b < 255
? Color (r, g, b + step)
: g < 255
? Color (r, g + step, 0)
: r < 255
? Color (r + step, 0, 0)
: Color (0, 0, 0)
const setElemColor = (elem, { r, g, b }) =>
elem.style.backgroundColor = `rgba(${r}, ${g}, ${b}, 1)`
const delay = (x, ms) =>
new Promise (r => setTimeout (r, ms, x))
const effect = f => x =>
(f (x), x)
const FPS =
1000 / 60
let RUNNING =
true
const main = async (elem, color = Color ()) =>
RUNNING
? delay (color, FPS)
.then (effect (color => setElemColor (elem, color)))
.then (color => main (elem, stepColor (color)))
: color
main (document.querySelector('#main'))
.then (console.log, console.error)
// => { r: 136, g: 8, b: 40 }
// stop after 5 seconds
setTimeout (() => RUNNING = false, 5000)
#main {
width: 100px;
height: 100px;
background-color: rgb(128, 128, 128);
}
<div id="main"></div>
<p>runs for 5 seconds...</p>
关于javascript - 运行多个递归 Promise 并在请求时中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48349721/