嵌套for循环结合从Nodejs中的API获取数据?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (331)

我的方案如下:我想从中获取一个API。API返回一个json,其中包含一个名为“assets”的数组。这个数组大小永远是20.现在,我像这样调用端点:

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

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

我想检查1000个项目,这意味着我想称此获取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等等......

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

提问于
用户回答回答于

而不是for..loop,你可以使用递归或Promises。

递归::

let insertToDB = function (records, cb) {
  if (!records.length) return cb();
  let record = records.shift();//assuming records is an array
  // Insert record into DB1
  insertToDB(records, cb);
};

let loop = function (count, offset, cb) {
 if (!count) return cb();
 fetch(
    `https://api.example.io/api/v1/assets/?offset=${offset}`
 )
 insertToDB(recordsFromFetch, function () {
    offset += 20;
    --count;
    loop(count, offset, cb)
 })
};


loop(50, 0, function () {
  console.log("All Done");
})

承诺::我没有运行它,所以可能会出现一些语法错误,但足够让你看懂:

let insertToDB = function (record) {
    return new Promise(function (resolve, reject) {
    // Insert record into DB then call resolve
    resolve();
    })
};

let fetchPhase = function (offset) {
    fetch(
    `https://api.example.io/api/v1/assets/?offset=${offset}`
   )
    let dbAll = [];
   for (let j = 0; j < 20; j++) {
    // assuming you get records from fetch , pass record to be added to db in the parameter
    dbAll.push(insertToDB(records[j]))
}
 return Promise.all(dbAll)
};

let all = [];

let offset = 0;

for (let i = 0; i < 50; i++) {
    all.push(fetchPhase(i));
}

Promise.all(all)
.then(function () {
    console.log("ALL DONe");
})
用户回答回答于

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

// 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
});

扫码关注云+社区

领取腾讯云代金券