我想创建一个队列,在该队列中,我总是并行执行两个httpRequest。当一个请求完成时,下一个应该开始,以便总是两个并行运行。 我想合并结果并在所有请求完成后将其整体返回。
我的第一个尝试是创建一个Subject(队列),并在其中使用queue.next(url)传递URL。剧院结束后,我立即完成了本主题。我使用mergeMap将执行一次限制为两个请求(queueObservable)。
我订阅queueObservable并将响应添加到数组(列表)。 然后,我等待queueObservable的承诺,该承诺应在Observable完成时解决。
但是正在发生的是,即使在执行下一个下一个回调之前和在可观察对象完成之前,承诺也会得到解决。
在我的第二次尝试中,我创建了一个新的Promise并在queueObservable的已完成回调中解决它。这种方法很好用,但是我不明白为什么第一种方法不起作用。
你能告诉我吗? 有没有更聪明的解决方案来解决这个问题?
亲切的问候, 大卫
import { of, Subject } from 'rxjs';
import { delay, mergeMap } from 'rxjs/operators';
const testFunction1 = async () => {
const queue = new Subject();
const list = [];
const queueObservable = queue.pipe(mergeMap(val => of(val).pipe(delay(500)), 2));
queueObservable.subscribe((next) => {
console.log(next);
list.push(next);
}, () => { },
(complete) => {
console.log('Observable1 completed');
});
queue.next('HTTP1: 1');
queue.next('HTTP1: 2');
queue.next('HTTP1: 3');
queue.next('HTTP1: 4');
queue.complete();
await queueObservable.toPromise(); // I expect this to resolve when all values passed the mergeMap pipe.
return list;
}
const testFunction2 = async () => {
const list = [];
await new Promise(resolve => {
const queue = new Subject();
const queueObservable = queue.pipe(mergeMap(val => of(val).pipe(delay(500)), 2));
queueObservable.subscribe((next) => {
console.log(next);
list.push(next);
}, () => { },
() => {
console.log('Observable2 completed'); // This gets called when all values passed mergeMap pipe.
resolve();
});
queue.next('HTTP2: 1');
queue.next('HTTP2: 2');
queue.next('HTTP2: 3');
queue.next('HTTP2: 4');
queue.complete();
});
return list;
}
testFunction1().then(res => {
console.log('Over1: ' + JSON.stringify(res));
});
testFunction2().then(res => {
console.log('Over2: ' + JSON.stringify(res));
});
编辑: 此图基本上显示了我要归档的内容。当所有其他可观察变量完成时,管道可观察的变量(queueObservable)完成。当我在管道可观察对象上调用toPromise时,它仅应在管道可观察对象完成时解决(至少这是我对toPromise功能的理解)。
答案 0 :(得分:0)
您能做这样的事(fiddle)
const urlsSink = new Subject();
const responses = urlsSink.pipe(bufferCount(2), mergeMap((urls) => {
return combineLatest(urls.map(url => makeHttpRequest(url)));
}));
然后,您可以订阅responses
并将URL推送到urlsSink
中。 bufferCount
将URL分为两个组。 combineLatest
会将两个HTTP观察值合并为一个合并的HTTP观察值。
答案 1 :(得分:0)
这是因为您正在延迟这些值,这些值尚未发出,但是您完成了主题。完成主题后,应兑现诺言。
尝试一下
queueObservable
这将迫使案例1起作用,但这不适合提出请求。
似乎queue
的承诺跟随toArray
的完成。
您可以使用const queueObservable = from(listOfURL).pipe(
mergeMap(val => of(val).pipe(delay(500)), 2),
mergeMap(val => fetch(url + val)),
toArray(),
);
运算符合并到结果。
const Ajv = require('ajv')
const ajv = new Ajv()
const schema = {
query: {
type: 'object',
required: ['locale'],
properties: {
locale: {
type: 'string',
minLength: 1,
},
},
},
}
const test = {
a: 1,
}
const validate = ajv.compile(schema)
const valid = validate(test)
console.log(valid) // TRUE