【问题标题】:Set timeout issue with promise (react+redux)用 promise 设置超时问题(react+redux)
【发布时间】:2018-03-30 01:47:34
【问题描述】:

我正在为我的有趣测试项目设计一些机制原型,因为我知道我需要延迟很多我认为我需要 Promise 的事情。

然而,事实证明它并没有像我想象的那样工作。虽然目前这对我来说不是问题,但我知道稍后我将不得不解决这个问题。

代码如下:

if(nextProps.mechanics.turn === 'enemy'){
            let enemyTurnPromise = new Promise((resolve, reject) =>{
                let i = 0;
                _.forEach(this.props.enemies, (enemy, index) =>{
                    setTimeout(this.handleEnemyAttack, 1000 * index)
                    i++;
                })
                resolve(i)
            })
            enemyTurnPromise.then(r =>{
                console.log('test', r);
                this.props.switchTurn('ally')

            })

        }

目前我将状态切换为“敌人”,它会立即切换回“盟友”并打印“i”值,而 setTimeout 仍在缓慢解决。

没有一些奇怪的回调块,有没有什么优雅的方法来解决这个问题? async/await 可以帮助解决这个问题吗?或者也许是一些可以消除大量不必要代码的库?

【问题讨论】:

  • 我认为是XY Problem。您没有具体说明问题是什么,而是尝试将其抽象出来并希望得到该抽象问题的答案。

标签: javascript reactjs promise


【解决方案1】:

主要问题是你解决得太早了。在所有这些超时完成之前,您不想解决。

最简单的方法是从启用承诺的setTimeout 开始,如下所示:

const setTimeoutPromise = delay => new Promise(resolve => {
    setTimeout(resolve, delay);
});

然后,现在坚持使用 promise 语法并假设 this.props.enemies 是一个数组,您可以使用 map 为每个敌人创建一个 promise,并使用 Promise.all 等待所有这些完成:

if(nextProps.mechanics.turn === 'enemy') {
    Promise.all(this.props.enemies.map((enemy, index) =>
        setTimeoutPromise(1000 * index).then(() => this.handleEnemyAttack(enemy))
    )).then(r => {
        console.log('test', /*...not sure what `r` is meant to be here... */);
        this.props.switchTurn('ally')
    })
}

另一种选择是使用reduce 并持续延迟,并等待每个敌人的攻击在下一次之前完成:

if(nextProps.mechanics.turn === 'enemy') {
    this.props.enemies.reduce((p, enemy) =>
        p.then(() => setTimeoutPromise(1000)).then(this.handleEnemyAttack(enemy))
    , Promise.resolve())
    .then(r => {
        console.log('test', /*...not sure what `r` is meant to be here... */);
        this.props.switchTurn('ally')
    })
}

async/await 可以帮助解决这个问题吗?

是的,大时代:

if(nextProps.mechanics.turn === 'enemy') {
    (async () => {
        for (const enemy of this.props.enemies) {
            await setTimeoutPromise(1000);
            this.handleEnemyAttack(enemy);
        }
        console.log('test', /*not sure what r is meant to be here*/);
        this.props.switchTurn('ally')
    }).catch(e => {
        // Handle error
    });
}

如果上面的if 已经在async 函数中,我们可以删除该位:

if(nextProps.mechanics.turn === 'enemy') {
    for (const enemy of this.props.enemies) {
        await setTimeoutPromise(1000);
        this.handleEnemyAttack(enemy);
    }
    console.log('test', /*not sure what r is meant to be here*/);
    this.props.switchTurn('ally')
}

【讨论】:

  • async/await 听起来很棒,非常感谢,现在我比 1 小时前更了解它了。
猜你喜欢
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多