【问题标题】:How can I run promises in sequence and dynamically如何按顺序动态运行 Promise
【发布时间】:2018-12-28 22:42:48
【问题描述】:

在我的 Web 应用程序中,我可以运行代码块(它创建一个 Promise 并等待结果出来)。每次用户运行一个段落时,我都会将它的 id 添加到一个数组中并按顺序运行它。

runSequentially(paragraphsId) {
    paragraphsId.reduce((promise, paragraphId) => {
        return promise.then(() => this.runParagraph(paragraphId))
    }, Promise.resolve())
}

addToQueue(paragraphId) {
    if (this.state.runQueue.indexOf(paragraphId) === -1) {
        this.setState({
            runQueue: [...this.state.runQueue, paragraphId]
        }, () => this.runSequentially(this.state.runQueue))
    }
}

runParagraph(paragraphId) {
    const newParagraphResults = { ...this.state.paragraphResults }
    delete newParagraphResults[paragraphId]

    const newParagraphs = { ...this.state.paragraphs }
    const newParagraph = newParagraphs[paragraphId]
    newParagraph.isRunning = true
    newParagraph.status = 'running'
    this.setState({
        paragraphs: newParagraphs,
        paragraphResults: newParagraphResults
    })

    const paragraphs = [
        {
            identifiers: { id: paragraphId },
            title: newParagraph.title,
            source: newParagraph.source
        }
    ]

    const notebookLibraries = Object.values(this.state.notebookLibraries)

    this.runController = new AbortController()
    return this.service.notebookRun(this.notebookId, paragraphs, notebookLibraries, this.runController)
        .then(result => {
            Object.entries(result.paragraphs).forEach(entry => {
                if (entry[0] === 'default_paragraph') {
                    return
                }
                const paragraphId = entry[0]
                const paragraphResult = entry[1]
                newParagraphResults[paragraphId] = paragraphResult
                paragraphResult.exception ? this.setParagraph(paragraphId, { status: 'failed' }) :
                    this.setParagraph(paragraphId, { status: 'passed' })
            })
            this.setState({ paragraphResults: newParagraphResults })
        })
        .catch((error) => {
            if (error.name === 'AbortError') {
                return Promise.reject(error)
            }
            const message = `Execution failed for reason: ${error.reason}.`
            this.handleServiceError('notebook', 'run', message)
        })
        .finally(() => {
            const newRunQueue = [ ...this.state.runQueue ]
            newRunQueue.shift()
            this.setParagraph(paragraphId, { isRunning: false })
            this.setState({ runQueue: newRunQueue })
        })
}

当用户运行一个段落时,我们调用addToQueue,然后调用runSequentially。当一个 promise 完成时,我们移动队列(在 runParagraph 方法中),但是如果我们在第一个段落完成之前运行另一个段落,这将迭代相同的 promise 两次。

您将如何处理这个动态的承诺队列?在这种情况下递归可以工作吗?

【问题讨论】:

  • @lukaleli 我不认为这是一个严格的重复,因为这里的 OP 似乎希望能够动态添加到队列中,而您链接的问题是针对静态数组。
  • 能否请您也显示 runParagraph() 代码?您可能会喜欢,因为我认为您的意思是递归地,而不是将所有 runParagraph 承诺与减少联系在一起,并获得前一个承诺的解决方案,开始运行下一个,以便您有时间从队列中删除一个块。如果他们必须等待彼此的解决方案,就没有理由已经做出承诺。
  • @Shilly 我已经添加了 runParagraph 代码

标签: javascript reactjs promise


【解决方案1】:

您应该在您的班级中将另一个属性(也许queue 不是最好的名称,因为您已经有state.runQueue)初始化为Promise.resolve(),并让它成为您的顺序队列的未决承诺。然后你可以这样做:

runSequentially(...paragraphsId) {
  this.queue = paragraphsId.reduce((promise, paragraphId) => {
    return promise.then(() => this.runParagraph(paragraphId))
  }, this.queue)
}

addToQueue(paragraphId) {
  if (this.state.runQueue.indexOf(paragraphId) === -1) {
    this.setState({
      runQueue: [...this.state.runQueue, paragraphId]
    }, () => this.runSequentially(paragraphId))
  }
}

runSequentially() 现在接受增量更新而不是整个runQueue,并且您不应将queue 存储在您的state 变量中,因为promise 本身不会影响您的渲染,所以它是安全的。

【讨论】:

    【解决方案2】:

    如果我们在第一个段落完成之前运行另一个段落,这将重复相同的承诺两次。

    您需要将promise 队列作为属性保留在您的状态中,而不是每次调用runSequentially 时都创建一个新的Promise.resolve()。有关示例实现,请参阅 here

    如果您想通过setState 严格管理您的队列,则根本不需要runSequentially 方法。 runParagraph 本身会 a) 检查它是否已经在运行,b) 完成后,将数组中的下一个元素出列并再次调用 runParagraph,直到没有剩余。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-17
      • 2018-09-16
      • 1970-01-01
      • 2015-10-02
      • 1970-01-01
      • 2017-11-16
      • 2022-01-18
      相关资源
      最近更新 更多