我想使用返回可观察对象的对象方法转换并替换数组中的所有单词。问题是由于结果是异步的,因此在错误的索引处错误地覆盖了结果的值。如果我有一个同步函数,我可以简单地在for循环中调用该函数。在这种情况下我该怎么做?
for(let word in this.words){
var i = Object.keys(this.words).indexOf(word);
this.convertor.get(this.words[i].value).subscribe( (result) => {
this.words[i].value = result; //The value of i is incorrect
});
}
答案 0 :(得分:6)
您可以使用将额外参数绑定到的简单函数来解决此问题:
this.convertor.get(this.words[i].value).subscribe( function (i, result) {
this.words[i].value = result;
}.bind(this, i));
.bind()
返回一个(新)函数,它类似于您应用bind
的函数,但会预先确定实际调用该函数时的一些内容:
this
设置为您在第一个参数中传递给bind
的内容。与箭头函数相反,老式函数通常根据函数的调用方式获得this
值 - 这种行为不是您想要的,因此它是bind
的一个受欢迎的特性;
可以预先修复一些参数。无论你通过bind
传递的其他参数都成为该函数的第一个参数的值 - 它们不是由实际调用决定的。在这种情况下,传递 i 的值,因此该函数将获取该值作为其第一个参数,无论以后如何调用它。
在调用(返回)时传递给函数的任何其他参数都将遵循前面提到的参数。在这种情况下,实际调用将传递 result 的值,因此该函数应该处理两个参数:一个由bind
提供,另一个由调用者提供。
这解决了您的问题,因为您可以将 i 的正确值传递给每个函数,而不会丢失this
的值。
答案 1 :(得分:1)
另一种选择可能是forEach
,因此您不必跟踪索引并处理例如使用first()
清理订阅的情况。
this.words.forEach((word, i) => {
this.obs$(word)
.pipe(
tap(v => (this.words[i].value = v)),
first()
)
.subscribe();
});
https://stackblitz.com/edit/static-iterable-value-from-obs?file=src/app/app.component.ts