我有一些与DB合作的功能:
setupData(param) {
return Observable.create((observer) => {
this.db.executeSql('SELECT .... ?', param).then(() => {
console.log('DB QUERY DONE');
observer.complete();
}, (error) => {
observer.error(error);
});
});
}
在另一个函数的循环中,我需要按顺序运行这些observable。我是这样做的:
processData() {
...
let observers = [];
storage.forEach((data) => {
observers.push(this.setupData(data));
});
Observable.concat(observers).subscribe(() => {
console.log('NEXT');
}, () => {
console.log('ERROR');
}, () => {
console.log('COMPLETE');
});
}
所以我的输出:
下一个
下一个
下一个
...
下一个
下一个完整的
但我从未见过" DB QUERY DONE"。每个可观察者都没有订阅。如果我用forkJoin替换concat - 我看到了我的期望,但我需要运行SEQUENTIALLY,而不是并行......有什么解决方案吗?
答案 0 :(得分:2)
你真正需要的是concatMap。您可以在observable上执行此运算符,它将执行的操作。
取下一个值。
对此值执行一个函数,该函数应返回一个observable。
开始收听此可观察对象,并将此观察值中的值发送到下一个。
一旦这个观察者停止发射,从源观察中取下一个值并重复。
代码明智,这看起来像这样:
const processData = () => {
let storageIds$ = Rx.Observable.from(["1", "2", "3"]);
storageIds$.concatMap((val) => {
return setupData(val);
}).subscribe(() => {
console.log('NEXT');
}, () => {
console.log('ERROR');
}, () => {
console.log('COMPLETE');
});
}
你可以看到我已经从数字1,2,3创建了一个可观察的storageIds$
。然后我在这个observable上执行了一个concatMap。我只是调用setupData方法,该方法返回一个observable,并立即返回。这将为您提供预期的行为。
可在此处找到完整的jsbin示例: http://jsbin.com/katame/edit?js,console