Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何按顺序动态运行承诺_Javascript_Reactjs_Promise - Fatal编程技术网

Javascript 如何按顺序动态运行承诺

Javascript 如何按顺序动态运行承诺,javascript,reactjs,promise,Javascript,Reactjs,Promise,在我的web应用程序中,我可以运行代码块(它创建承诺并等待结果出来)。每次用户运行段落时,我都会将其id添加到数组中并按顺序运行 runSequentially(paragraphsId) { paragraphsId.reduce((promise, paragraphId) => { return promise.then(() => this.runParagraph(paragraphId)) }, Promise.resolve()) }

在我的web应用程序中,我可以运行代码块(它创建承诺并等待结果出来)。每次用户运行段落时,我都会将其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
,然后调用
runsequence
。当一个承诺得到解决时(在
runparation
方法中),我们会移动队列,但是如果我们在第一个段落完成之前运行另一个段落,这将在同一个承诺上迭代两次


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

您应该初始化另一个属性(可能
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))
  }
}

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

您应该初始化另一个属性(可能
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))
  }
}
runsequential()
现在接受增量更新,而不是整个
runQueue
,并且您不应该将
queue
存储在
state
变量上,因为承诺本身不会影响渲染,所以它是安全的

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

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

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

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

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


如果希望通过
setState
严格管理队列,则根本不需要
runsequential
方法<代码>运行段落本身将a)检查它是否已经在运行,b)完成后从数组中取出下一个元素并再次调用
运行段落
,直到没有剩余的元素。

异步/等待如何?@lukaleli的可能重复我不认为它是严格的重复,因为这里OP似乎希望能够动态地添加到队列中,而您链接的问题是静态数组。您能同时显示runparation()代码吗?你可以像我想你的意思一样,递归地,不要把所有的runparation承诺和一个reduce链接在一起,并有上一个承诺的解析,开始运行下一个,这样你就有时间从队列中删除一个块。如果他们必须等待对方的决议,没有理由已经做出承诺。@Shilly我已经添加了运行段落代码async/await如何?@lukaleli的可能重复我不认为它是严格的重复,因为这里OP似乎希望能够动态地添加到队列中,而您链接的问题是静态数组。您能同时显示runparation()代码吗?你可以像我想你的意思一样,递归地,不要把所有的runparation承诺和一个reduce链接在一起,并有上一个承诺的解析,开始运行下一个,这样你就有时间从队列中删除一个块。如果他们必须等待对方的决议,那么没有理由已经做出承诺。@Shilly我已经添加了运行段代码