javascript - RXJS + Axios 错开网络请求

标签 javascript promise rxjs axios

我使用的 API 具有非常严格的速率限制,我需要从数组中的名称向同一端点发送大量请求。我设置了一个简单的演示项目并尝试了这个(以及可能的变体):

const pokemon = ['ditto', 'bulbasaur', 'charizard', 'pikachu'];
const obs = pokemon.map((pk, index) => {
  return from(axios.get(`https://pokeapi.co/api/v2/pokemon/${pk}`)).pipe(delay(1000),map(res => {
    return {id: res.data.id, name: res.data.name, height: res.data.height};
  }));
});

concat(obs).subscribe(data => {
  console.log(data);
});

但是 Axios.get() 在创建时全部触发,而 concat().subscribe() 仅记录 4 个可观察值。如果我订阅了 from().pipe(),那么在一秒钟后,所有 4 个注销都会立即注销,但是我订阅的是一个很差的订阅。

我确定的解决方案感觉很麻烦,我不得不相信有更好的方法:

const axios = require('axios');
const { forkJoin, from } = require('rxjs');
const { map } = require('rxjs/operators');

const pokemon = ['ditto', 'bulbasaur', 'charizard', 'pikachu'];

const obs = pokemon.map((pk, index) => {
  return from(new Promise(resolve => setTimeout(async () => {
    const prom = await axios.get(`https://pokeapi.co/api/v2/pokemon/${pk}`);
    resolve(prom);
  }, index*1000))).pipe(map(res => {
    console.log('fetched: ', pk);
    return {id: res.data.id, name: res.data.name, height: res.data.height};
  }))
})

forkJoin(obs).subscribe(data => {
  console.log(data);
});

这会延迟 axios.get() 的创建,如果我使用 node --require debugging-aid/network rxjs_axios_delay.js 运行,我可以看到延迟网络请求和我正在访问的真实 API 很高兴,但这感觉很复杂而且不是很“RXy”。

有人有更好的东西吗?

最佳答案

but the Axios.get()'s all fire off when they are created

这突出了 Promise 的一个非常有趣的特点:它们渴望。我认为 defer 运算符可以派上用场:

const pokemon = ['ditto', 'bulbasaur', 'charizard', 'pikachu'];

const obs = pokemon.map((pk, index) => {
  return defer(() => axios.get(`https://pokeapi.co/api/v2/pokemon/${pk}`)).pipe(delay(1000),map(res => {
    return {id: res.data.id, name: res.data.name, height: res.data.height};
  }));
});

concat(...obs).subscribe(data => {
  console.log(data);
});

StackBlitz demo .

defer 最酷的一点是它在订阅时计算给定的表达式(即调用回调函数)。 这意味着您还可以执行以下操作:

let dep$ = of('A');
const src$ = defer(() => dep$);

if (someCondition) {
  dep$ = of('B')
}

// if `someCondition` is true, `dep$` will be `of('B')`
src$.pipe(...).subscribe()

关于javascript - RXJS + Axios 错开网络请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65759799/

相关文章:

javascript - 如果没有找到任何项目,则执行 else 语句

javascript - js : promises inside a while- true loop

rxjs - 在 BehaviorSubject 中更新 self 时如何避免无限循环?

angular - 在响应中获取状态零而不是 401

angular - 如何在不触发新发射的情况下获取可观察值的值

javascript - 我们可以使用 jquery 启用浏览器位置吗

javascript - Jquery切换菜单问题

javascript - 如何使这个脚本起作用

javascript - jQuery 时,中止多个 Ajax

javascript - Angular 自定义指令在 promise 解析后未设置值