首页 > 解决方案 > 嵌套 for 循环与从 Nodejs 中的 API 获取数据相结合?

问题描述

我的场景如下:有一个我想从中获取的 API。API 返回一个 json,其中包含一个名为“assets”的数组。这个数组大小将始终为 20。现在,我这样调用端点:

 fetch(
     `https://api.example.io/api/v1/assets/?offset=${offset}`
 )

如果偏移量为 0,它将返回 0 - 20 个资产的数组,如果偏移量为 20,它将返回 20 到 40,依此类推。

我想检查 1000 个项目,这意味着我想调用这个 fetch 1000/20 = 50 次。每当我调用 fetch 时,我都想遍历这 20 个项目并将它们插入到我的数据库中。问题是我不能做这样的事情:

let offset=0;

for(let i = 0; i < 50; i++ {
    fetch(
       `https://api.example.io/api/v1/assets/?offset=${offset}`
    )
    for(let j = 0; j < 20; j++){
    // Insert into DB
    }
    offset+=20;
}

由于 JS 的异步特性。每当我尝试执行此操作时,它会多次调用值为 0 的 fetch 以获得偏移量,它不会等到嵌套的 for 循环完成,而是调用它 20 和更高版本的 40 等等......

实现这种行为的正确方法是什么?

标签: javascriptnode.jsasynchronouscallbackpromise

解决方案


我从我的一个 nodeJS 存储库中删除了以下内容,因为它使用异步代码来解决一个非常相似的问题:

// Throttling is important because you don't want to
// overload the API
const createThrottle = require('async-throttle');
const throttle = createThrottle(2);

// First push all the links into an array using
// the offset
const links = [];
for (let offset = 0; offset < 100; offset += 20) {
  links.push(`https://api.example.io/api/v1/assets/?offset=${offset}`);
}

// Next create an array of promises by `map`ing
// over the links using `fetch`.
// Notice I've used throttle here to slow down the hits on
// the API
const promises = links.map(link => throttle(async => () {
  const res = await fetch(link);
  return await res.json();
}));

// Once all the promises are complete, iterate over their datasets
Promise.all(promises).then(datasets => {
  // iterate over datasets
});

推荐阅读