Javascript 在Foreach内部调用Subscribe
我有一个包含问题列表的调查,每个问题都包含多项选择答案列表。我试图把这个推到我的后端,但根据我的数据库,它只推了调查的第一个问题。我确保问题和答案正确插入,并使用Graphql测试了突变Javascript 在Foreach内部调用Subscribe,javascript,angular,foreach,rxjs,subscribe,Javascript,Angular,Foreach,Rxjs,Subscribe,我有一个包含问题列表的调查,每个问题都包含多项选择答案列表。我试图把这个推到我的后端,但根据我的数据库,它只推了调查的第一个问题。我确保问题和答案正确插入,并使用Graphql测试了突变 this._surveyService.addSurveyToInitiative(this._initiativeId, this.name, this.category, "TBD").subscribe(surveyData => { this.survey.quest
this._surveyService.addSurveyToInitiative(this._initiativeId, this.name, this.category, "TBD").subscribe(surveyData => {
this.survey.questions.forEach(question => {
this._surveyService.addQuestionToSurvey(surveyData.data.createSurvey.survey.id, question.question).subscribe(questionData=> {
question.multipleChoiceAnswers.forEach(answer => {
this._surveyService.addMultipleChoiceAnswerToQuestion(questionData.data.addQuestionToSurvey.newQuestion.id, answer).subscribe()
})
})
})
})
}
你不应该连锁订阅。forEach也是一个最终操作,这意味着它不会返回任何内容。你应该改用 更好的方法是使用以下方法:
this._surveyService.addSurveyToInitiative(this._initiativeId, this.name, this.category, "TBD")
.pipe(
map(surveyData => surveyData.data.createSurvey.survey.id),
mergeMap(surveyId => this.survey.questions.map(question => this._surveyService.addQuestionToSurvey(surveyId, question.question))),
map(questionData => questionData.data.addQuestionToSurvey.newQuestion.id),
mergeMap(questionId => question.multipleChoiceAnswers.forEach(answer => this._surveyService.addMultipleChoiceAnswerToQuestion(questionId, answer)))
).subscribe();
乍一看,问题似乎不是RxJS或
subscribe
。你的服务电话可能是罪魁祸首。也就是说,很难调试
在循环中嵌套subscribe
和/或调用subscribe
基本上总是一种反模式。您正在肆意地混合命令式和函数式编程风格——这并不是说您不能让它工作,而是挑逗出哪里出了问题(更不用说在将来维护/扩展它)变得更具挑战性
首先,让我们从更具功能性的角度重写:
this.\u surveyService.addSurveyToInitiative(
这个,
这个名字,
这一类,,
“待定”
).烟斗(
地图(测量数据=>
this.survey.question.map(问题=>
此.\u surveyService.addQuestionToSurvey(
surveyData.data.createSurvey.survey.id,
问题
).烟斗(
映射(questionData=>({question,questionData}))
)
)
),
合并映射(serviceCalls=>merge(…serviceCalls)),
map({question,questionData})=>
问题.multipleChoiceAnswers.map(答案=>
此.\u surveyService.add多回音回答问题(
questionData.data.addQuestionToSurvey.newQuestion.id,
回答
)
)
),
合并映射(serviceCalls=>merge(…serviceCalls))
).subscribe();
这里,这一行:mergeMap(serviceCalls=>merge(…serviceCalls))
(见两遍)实际上是您订阅所有呼叫的方式
这应该更容易调试。现在,您可以点击流的任何部分,查看此时发生的情况
this.\u surveyService.addSurveyToInitiative(
这个,
这个名字,
这一类,,
“待定”
).烟斗(
轻触(surveyData=>console.log(“处理surveyData:,surveyData)),
地图(测量数据=>
this.survey.question.map(问题=>
此.\u surveyService.addQuestionToSurvey(
surveyData.data.createSurvey.survey.id,
问题
).烟斗(
映射(questionData=>({question,questionData}))
)
)
),
合并映射(serviceCalls=>merge(…serviceCalls)),
点击(questionAndData=>console.log(“处理questionAndData:”,questionAndData)),
map({question,questionData})=>
问题.multipleChoiceAnswers.map(答案=>
此.\u surveyService.add多回音回答问题(
questionData.data.addQuestionToSurvey.newQuestion.id,
回答
)
)
),
合并映射(serviceCalls=>merge(…serviceCalls))
).subscribe(x=>console.log(“完成处理最后一步,得到响应:”,x));
现在,您可以延迟
某些调用,或者使用concat(…
而不是merge(…
)来了解流在做什么
旁白:
这里是同样的事情,只是更简洁一点(我们结合合并调用):
this.\u surveyService.addSurveyToInitiative(
这个,
这个名字,
这一类,,
“待定”
).烟斗(
合并地图(调查数据=>
合并(…this.survey.question.map(问题=>
此.\u surveyService.addQuestionToSurvey(
surveyData.data.createSurvey.survey.id,
问题
).烟斗(
映射(questionData=>({question,questionData}))
)
))
),
合并地图({question,questionData})=>
合并(…question.multipleChoiceAnswers.map(答案=>
此.\u surveyService.add多回音回答问题(
questionData.data.addQuestionToSurvey.newQuestion.id,
回答
)
))
)
).subscribe();
更新#1
你确定吗
this.survey.question.map(question =>
是吗?似乎是一个奇怪的命名惯例。我希望有更类似的东西
this.survey.questions.map(question =>
首先感谢您的帮助!我尝试运行您的代码,从语法上看它可以正常工作,但在后端它与我的代码的工作方式相同。因此它将第一个问题推送到调查中,而没有任何答案。(this.survey.questions是正确的,因为调查中有一个问题列表)。再次感谢。我的回答的一部分是为了帮助您调试。在您的问题中,您出现的问题并不明显/可见。您必须更新您的问题,然后才能希望获得进一步的帮助。