我有一个具有以下功能的 react 组件:
alreadyUpvoted() {
return this.state.upvotes.indexOf(this.props.context.userId) !== -1
}
alreadyDownvoted() {
return this.state.downvotes.indexOf(this.props.context.userId) !== -1
}
addUpvote() {
this.setState(prev => ({
upvotes: prev.upvotes.concat(this.props.context.userId),
upvoted: true,
votes: prev.votes + 1,
}), () => {
console.log('add upvote', this.state)
})
}
removeUpvote() {
var new_upvotes = this.state.upvotes.concat()
new_upvotes.pop(this.props.context.userId)
this.setState(prev => ({
upvotes: new_upvotes,
upvoted: false,
votes: prev.votes - 1,
}), () => {
console.log('remove upvote', this.state)
})
}
addDownvote() {
this.setState(prev => ({
downvotes: prev.downvotes.concat(this.props.context.userId),
downvoted: true,
votes: prev.votes - 1,
}), () => {
console.log('add dowvote', this.state)
})
}
removeDownvote() {
var new_downvotes = this.state.downvotes.concat()
new_downvotes.pop(this.props.context.userId)
this.setState(prev => ({
downvotes: new_downvotes,
downvoted: false,
votes: prev.votes + 1,
}), () => {
console.log('remove downvote', this.state)
})
}
postVotesData() {
var json = {
upvotes: this.state.upvotes,
downvotes: this.state.downvotes
}
json = JSON.stringify(json)
console.log(json)
const url = `/api/reddit/r/${this.props.subreddit}/posts/${this.props.postid}/`
fetch(url, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: json
})
.then(response => {
console.log('response status:', response)
return response.json()
})
.then(res => console.log('response data:', res))
}
我创建了一个 toggleUpvote
函数,它利用了上述所有函数:
toggleUpvote() {
if (this.alreadyDownvoted()) {
this.removeDownvote()
this.addUpvote()
}
else if (this.alreadyUpvoted()) {
this.removeUpvote()
}
else {
this.addUpvote()
}
this.postVotesData()
}
这里的问题是 this.postVotesData()
在 if-else block 完成之前执行。
对于当前状态,控件应该转到 else block 。但是,this.postVotesData()
中的 console.log
在 addUpvote
中的 console.log
之前执行!!
在当前状态下,upvotes
数组在执行 else 后应该有一个值,并且该数组应该在 PUT 中使用。但是,空数组被PUT,然后值被添加到数组中。
我还希望 if block 内的函数按顺序执行。我该如何解决这个问题?
最佳答案
这就是异步 JavaScript 的工作原理。我相信您正在执行异步操作,例如 fetch 调用或 React 的 setState()。 js 中的它们(以及许多其他东西)都是异步的。 为了解决这个问题,您需要使用回调或 promise 。使用 Promise 时,您可以使用 async-await 语法来获得干净的代码。
async toggleUpvote() {
if (this.alreadyDownvoted()) {
await this.removeDownvote()
await this.addUpvote()
}
else if (this.alreadyUpvoted()) {
await this.removeUpvote()
}
else {
await this.addUpvote()
}
await this.postVotesData()
}
为此,removeUpvote、addUpvote 和 postVotesData 需要返回 Promise。
如果在这些函数中调用setState,则需要提供setState的回调。或者您可以使用功能集状态模式。
避免此问题的一个简单修复方法是从类似于以下内容的函数返回一个 promise ,并使用上面建议的 async-await 语法。
addUpvote() {
return new Promise((resolve, reject) => {
this.setState(prev => ({
upvotes: prev.upvotes.concat(this.props.context.userId),
upvoted: true,
votes: prev.votes + 1,
}), () => {
console.log('add upvote', this.state)
return resolve(); // Signal that the operation has finished
})
})
}
关于javascript - Reactjs - 排序 if else 和外部 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51464979/