Javascript RxJS获取订阅回调的完成结果
我是RxJS初学者,我想让我的代码更干净 这是我写的代码,我在接收完成结果时遇到问题 我想让我的代码更干净,在订阅回调中获得结果,而不使用其他主题来接收结果 以下是我的代码rxjs 7.0.1:Javascript RxJS获取订阅回调的完成结果,javascript,typescript,rxjs,Javascript,Typescript,Rxjs,我是RxJS初学者,我想让我的代码更干净 这是我写的代码,我在接收完成结果时遇到问题 我想让我的代码更干净,在订阅回调中获得结果,而不使用其他主题来接收结果 以下是我的代码rxjs 7.0.1: 从“颜色/安全”导入颜色; 从'rxjs'导入{Subject}; 从“rxjs/operators”导入{throttle}; 接口IEventTask{ id:string, createdTime:编号 } 设全局_计数器:数=0; const mockHTTPRequest=async(事件:I
从“颜色/安全”导入颜色;
从'rxjs'导入{Subject};
从“rxjs/operators”导入{throttle};
接口IEventTask{
id:string,
createdTime:编号
}
设全局_计数器:数=0;
const mockHTTPRequest=async(事件:IEventTask)=>{
返回(Promise.resolve().then(async()=>{
等待新的承诺((决心)=>{
全局.setTimeout(解析,1000);
});
如果(event.id=='01'){
抛出新错误(`Error:${event.id}`);
}
const result=`result:${event.id}`;
//我不知道如何得到结果,所以我发布到另一个订阅者
下一步(结果);
返回结果;
}))
.catch((错误)=>{
控制台错误(error);
})
}
常量主题=新主题();
主题
.烟斗(
节气门(模拟HttpRequest{
前导:真,尾随:真
})
)
.订阅({
下一步:(值)=>{
log(`colors.blue(`starting`)}任务$${value.id}位于:${global_counter++}`);
},
错误:(错误)=>{
控制台错误(error);
},
完成:()=>{
//我怎样才能在这里得到结果?
console.log(`completed`);
}
});
//这不是我想要使用的代码,但我不知道如何让它变得简单。
const subscriber=新主题();
subscriber.subscribe((结果:字符串)=>{
log(${colors.green(`finished`)}${result}位于:${global_counter++}');
});
(异步()=>{
for(设i=1;i{
全局设置超时(()=>{
决心(正确);
}, 125);
});
常量值:IEventTask={
id:(i).toString().padStart(2,'0'),
createdTime:全局计数器++
};
主题。下一个(价值);
}
})();
非常感谢。在我看来,每当
subject
(变量)获得新值时,您都希望发出HTTP请求
因此,使用throttle
时要记住,它应该等待HTTP请求完成,并提供返回值。问题在于,油门不提供后者。(见附件)
我建议您改用switchMap
。它期望传递的函数返回一个可观察值,当它发出时,switchMap将转发该值。此外,每当发出一个新值时,它就完成了内部可观察性。这意味着,如果HTTP请求尚未完成,它将终止当前请求并发出新的请求。(见附件)
import { Subject, Observable, OperatorFunction, pipe, UnaryFunction } from 'rxjs';
import { filter, switchMap } from 'rxjs/operators';
const mockHTTPRequest = async (event: IEventTask) => {
return (Promise.resolve().then(async () => {
await new Promise((resolve) => {
setTimeout(resolve, 2000);
});
if (event.id === '01') {
throw new Error(`error: ${event.id}`);
}
const result = `result: ${event.id}`;
// This was needed in order to provide the id in the subscribe section
return {
id: event.id,
result
};
}))
.catch((error) => {
console.error(error);
// This was needed for the filter function to work
return undefined;
})
}
// this filters nullish values: null and undefined
function filterNullish<T>(): UnaryFunction<Observable<T | null | undefined>, Observable<T>> {
return pipe(
filter(x => x != null) as OperatorFunction<T | null | undefined, T>
);
}
const subject = new Subject<IEventTask>();
subject
.pipe(
switchMap(mockHTTPRequest),
filterNullish()
)
.subscribe({
next: (value) => {
console.log(`starting Task#${value.id} at: ${global_counter++}`);
},
error: console.error,
complete: () => {
// How can I get Promise resolved result here?
console.log(`completed`);
}
});
import colors from 'colors/safe';
import { Subject, Observable, OperatorFunction, pipe, UnaryFunction } from 'rxjs';
import { filter, mergeMap, tap } from 'rxjs/operators';
interface IEventTask {
id: string,
createdTime: number
}
let global_counter: number = 0;
function waitFor(time: number) {
return new Promise((resolve) => {
setTimeout(resolve, time);
})
}
function filterNullish<T>(): UnaryFunction<Observable<T | null | undefined>, Observable<T>> {
return pipe(
filter(x => x != null) as OperatorFunction<T | null | undefined, T>
);
}
const mockHTTPRequest = async (event: IEventTask) => {
return (Promise.resolve().then(async () => {
await waitFor(2000);
if (event.id === '01') {
throw new Error(`error: ${event.id}`);
}
return `result: ${event.id}`;
}))
.catch((error) => {
console.error(error);
return undefined;
})
}
const subject = new Subject<IEventTask>();
subject
.pipe(
tap(value => console.log(`${colors.blue(`starting`)} Task#${value.id} at: ${global_counter++}`)),
mergeMap(mockHTTPRequest),
filterNullish()
)
.subscribe({
next: (result) => {
console.log(`${colors.green(`finished`)} ${result} at: ${global_counter++}`);;
},
error: console.error
});
(async () => {
for (let i = 1; i <= 10; i++) {
await waitFor(125);
const value: IEventTask = {
id: (i).toString().padStart(2, '0'),
createdTime: global_counter++
};
subject.next(value);
}
})();