自己尝试实现了,但是结果不是自己想要的,而且如果多个异步轮询( A 轮询 -> B 轮询 -> C 轮询),可能就会使代码变得嵌套层级多,以下是实现的具体代码,有大佬指教指教么?
import { from, Observable, Subscriber } from 'rxjs';
import { delay, mapTo, repeatWhen } from 'rxjs/operators';
interface RetryOptions<T = any, P = any> {
try: (tryRequest: P) => Promise<T>;
tryRequest: P;
retryUntil: (response: T) => boolean;
maxTimes?: number;
tick?: number;
}
export const polling = <T = any, P = any>(options: RetryOptions<T, P>) => {
options = Object.assign(
{
maxTimes: 20,
tick: 1000
},
options
);
let result = null;
const notifier = () => {
// 计数最大尝试次数
let count = 0;
const loop = (producer: Subscriber<any>) => {
// 超过最大次数强制退出轮询
if (count >= options.maxTimes) {
producer.complete();
} else {
options
.try(options.tryRequest)
.then(res => {
producer.next(count++);
// 满足条件则退出轮询
if (options.retryUntil(res)) {
producer.complete();
} else {
// 不满足条件则继续轮询
loop(producer);
}
// 保存请求结果
result = res;
})
.catch(err => {
producer.error(err);
});
}
};
return new Observable(producer => {
loop(producer);
});
};
return from([0]).pipe(
delay(options.tick),
// 当满足条件是,进行一下轮轮询
repeatWhen(notifier),
// 转换结果
mapTo(() => result)
);
};
import { polling } from './polling';
let count = 0;
const mockRequest = (): Promise<string> => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (count < 6) {
resolve('pending');
} else {
resolve('finish');
}
count++;
}, 1000);
});
};
polling<string, number>({
try: mockRequest,
tryRequest: count,
retryUntil: res => {
return res === 'finish';
}
}).subscribe((response) => {
const result = response();
console.log(result);
if (result === 'finish') {
console.log('轮询结束');
}
// 这个轮询结束后应该怎么继续轮询比较好?
// 继续在这里 polling 下一个轮询吗?容易回调地狱啊
});
null
pending
pending
pending
pending
pending
pending
finish // 上面的都不输出,只输出最后一个结果,因为上面的我并不关注
轮询结束
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.