gpt4 book ai didi

javascript - 可以用生成器函数代替 promise 管理吗?

转载 作者:行者123 更新时间:2023-11-30 13:58:05 25 4
gpt4 key购买 nike

对于这个代码示例,您必须想象一系列关于移动机器人的动画(向左/向右移动,前进)

实际上它是一个具有更复杂动画的站点(加载ajax、加载图像、多个动画等..)我目前使用 promises 进行管理,但随着网站的发展,这部分的代码变成了一盘意大利面条。

这是我第一次做这样的事情,我想知道这是否真的是个好主意,因为这种做事方式对我来说真的很奇怪。
我有一种印象,我最终会发现自己遇到无法解决的问题。
在任何情况下,我当前的网站都会变成一场真正的噩梦,因为我必须更改一些动画,添加新的......

这个示例代码看起来正确吗?
我应该在那里改变什么吗?

const Root   = document.documentElement
, gRoot = getComputedStyle(Root)
, moving = [ {T:-30,L:0}, {T:0,L:+30}, {T:+30,L:0}, {T:0,L:-30} ]
;
var RotateDeg = 0
, RotateMov = 0
, posT = parseInt(gRoot.getPropertyValue('--PosT'))
, posL = parseInt(gRoot.getPropertyValue('--PosL'))
;
function F_1() // move forward
{
posT += moving[RotateMov].T
posL += moving[RotateMov].L

Root.style.setProperty('--PosT', posT + "px")
Root.style.setProperty('--PosL', posL + "px")
}
function T_L() // turn Left
{
RotateMov = (RotateMov +3) %4
RotateDeg -=90
Root.style.setProperty('--turn', RotateDeg + "deg")
}
function T_R() // turn Right
{
RotateMov = (RotateMov +1) %4
RotateDeg +=90
Root.style.setProperty('--turn', RotateDeg + "deg")
}
function R_0() // rotate to zero
{
RotateMov = 0
RotateDeg = 0
Root.style.setProperty('--turn', RotateDeg + "deg")
}
function disableButtons(OnOff)
{
Bt_Tab_A.disabled = OnOff
Bt_Tab_B.disabled = OnOff
}
function* Sequence(Tab_fct)
{
for( let fct of Tab_fct) yield fct
}

var iterator = Sequence([])

function nextSequence()
{
let command = iterator.next()
if (!command.done) command.value()
else disableButtons(false)
}

Bt_Tab_A.onclick=_=>
{
disableButtons(true)
iterator = Sequence( [ F_1, T_L, F_1, T_R, F_1, T_R, F_1, F_1, T_R, F_1, F_1, T_R, F_1, R_0 ] )
nextSequence()
}
Bt_Tab_B.onclick=_=>
{
disableButtons(true)
iterator = Sequence( [ T_L, F_1, T_R, F_1, T_R, F_1, T_R, F_1, R_0 ] )
nextSequence()
}
robot.addEventListener('transitionend', nextSequence )
:root {
--turn : 0deg;
--PosT : 110px;
--PosL : 90px;
}
#robot {
font-size : 16px;
width : 30px;
height : 30px;
background-color: aqua;
text-align : center;
line-height : 1.8em;
transition : all .5s linear;
transform : rotate( var(--turn) );
position:fixed;
top : var(--PosT);
left: var(--PosL);
}
<div id="robot">R</div>

<button id="Bt_Tab_A"> Sequence A</button>
<button id="Bt_Tab_B"> Sequence B</button>

欢迎提供提示和建议;)

最佳答案

在您的情况下,我觉得 Promise 是可行的方法。

根据我自己的经验法则(注意,这是自以为是):

  • 当您需要顺序执行异步操作时使用 promise。
  • 当您需要需要时生成结果时使用生成器函数。

在您的代码段中,您需要做的就是让动画按顺序运行,而不是在您需要时

此外,您会注意到您有多个函数依赖于单个变量(即 iterator)的当前状态(结果)。这样做的坏处是,当您的序列之间存在错误时,您将花费更多时间和精力来调试这种情况,因为一个函数中的一个更改可能会影响其他函数。您还有一个全局的 transitionend 事件监听器,乍一看非常令人困惑。

简而言之,使用生成器函数,顺序操作的流程很难理解。

下面的方法是使用 async/await。只修改了SequencenextSequence方法(里面有注释说明)。每个操作都包含在其自己的功能范围内。减少了对全局变量的依赖:

(抱歉,我在编写代码时将代码格式化为我的代码风格)

const Root = document.documentElement;
const gRoot = window.getComputedStyle(Root);
const moving = [
{
T: -30,
L: 0
},
{
T: 0,
L: +30
},
{
T: +30,
L: 0
},
{
T: 0,
L: -30
}
];

let RotateDeg = 0;
let RotateMov = 0;
let posT = parseInt(gRoot.getPropertyValue('--PosT'));
let posL = parseInt(gRoot.getPropertyValue('--PosL'));

function F_1(){
posT += moving[RotateMov].T;
posL += moving[RotateMov].L;

Root.style.setProperty('--PosT', posT + 'px');
Root.style.setProperty('--PosL', posL + 'px');
}

function T_L(){
RotateMov = (RotateMov + 3) % 4;
RotateDeg -= 90;
Root.style.setProperty('--turn', RotateDeg + 'deg');
}

function T_R(){
RotateMov = (RotateMov + 1) % 4;
RotateDeg += 90;
Root.style.setProperty('--turn', RotateDeg + 'deg');
}

function R_0(){
RotateMov = 0;
RotateDeg = 0;
Root.style.setProperty('--turn', RotateDeg + 'deg');
}

function disableButtons(OnOff){
Bt_Tab_A.disabled = OnOff
Bt_Tab_B.disabled = OnOff
}

async function Sequence(Tab_fct){
// Disable buttons before start
disableButtons(true);

for (let fct of Tab_fct)
// Run the animation one by one
await nextSequence(fct);

// Reenable buttons before end
disableButtons(false);
}

function nextSequence(fct){
return new Promise(res => {
// Move event listener here so that they dont depend on a global one.
// Use { once: true } to run this callback only once
window.addEventListener('transitionend', res, { once: true });

// Run the animation
fct();
})
}


Bt_Tab_A.onclick = () => {
Sequence([F_1, T_L, F_1, T_R, F_1, T_R, F_1, F_1, T_R, F_1, F_1, T_R, F_1, R_0]);
}

Bt_Tab_B.onclick = () => {
Sequence([ T_L, F_1, T_R, F_1, T_R, F_1, T_R, F_1, R_0 ]);
}
:root {
--turn : 0deg;
--PosT : 110px;
--PosL : 90px;
}
#robot {
font-size : 16px;
width : 30px;
height : 30px;
background-color: aqua;
text-align : center;
line-height : 1.8em;
transition : all .5s linear;
transform : rotate( var(--turn) );
position:fixed;
top : var(--PosT);
left: var(--PosL);
}
<div id="robot">R</div>

<button id="Bt_Tab_A">Sequence A</button>
<button id="Bt_Tab_B">Sequence B</button>

关于javascript - 可以用生成器函数代替 promise 管理吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56825817/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com