Search code examples
node.jsasync-awaitaxiosnedb

NodeJS wait for an axios+nedb function async/await to run next query


I want to use Axios + nedb in a NodeJS Script to gather data from an API into a local file. This is what I done so far:

var axios = require('axios');
var Datastore = require('nedb');
const fs = require('fs');

db = new Datastore({ filename: './../smb_share/art.db', autoload: true });

function getArt(limit, offset) {
    var config = {
      method: 'get',
      url: 'http://IPADD/api/data/2:1/?limit=' + limit + '&offset=' + offset',
      headers: { 
        'Accept': 'application/simple+json', 
        'Content-Type': 'application/json', 
        'Authorization': 'Basic XYZ'
      }
    };

    axios(config)
      .then(function (response) {
          response.data.erpDataObjects.forEach(element => {
              var doc = { number:element.head.number,
                          desc:element.head.desc
              };
              db.insert(doc, function (err, newDoc) {
                if(err =! null){
                  console.log(err);
                }   
            });
          });  
      })
    .catch(function (error) {
        console.log(error);
    });  
}

getArt(1000,0)
getArt(1000,1000)

This works fine, as long I am not gathering more data from the API. I need to call my function "getArt(limit, offset)" round about 400 times, because I get about 400000 docs from the API. I tried to do this with intervalTimers, so start every 5min the function and ++offset with 1000 each time the interval event is fired... Yes, I know that's weird, but it was the only way which worked for me at the moment. But when the API server is on heavy load, it takes too long for one query and I exceed the limit of call which end up in a mess.

My Question: how do I keep things clear and fire the functions when the function before is ready? I tried a lot of async/await stuff, but all ended up in errors or all was fired at the same time. What I basically need is something like ...

getArt(10000,0)
.then
getArt(10000,10000)
.then
getArt(10000,20000)
.then
...

But with the nested function of axios I don't know how to handle this with a promise. Can someone give me a hint?


Solution

  • Have you tried making getArt an async function and simply awaiting it?

    async function getArt(limit, offset){...}
    
    async function Name(){
      await getArt(10000, 1000); // wait to complete before moving on
      await getArt(10000, 2000); // only execute when above is done
    }
    
    Name();
    

    By not assigning the result of await, you simply tell your program to wait for this function to complete prior to moving on to next one.

    Side Note:

    Why not make a for loop which increments the offset and calls the getArt function?

    async function Name(){
      var limit = 10000;
      for(let offset = 0; offset < limit; offset += limit/10){
        await getArt(limit, offset);
      }
    }
    
    Name();
    

    I haven't tested this, but see no reason why it should not work.

    Additionally, (to follow good practice guidelines) you should wrap your await statements in a try-catch block to deal with errors like so:

    try{
      await getArt(limit, offset);
    }
    catch(err){
      console.error(err);
    }