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