简体   繁体   中英

Wait for function to end (in async.series) doesn't work as expected

I have a nodejs script that gets some json data containing item names and prices using an API, then checks the price of that item. The problem I have is that the function that checks the item name gets executed before the function that writes the price list ends. So if the price list file doesn't exist, it gives me 'no such file or directory' for the price list file. I searched for some time on the internet, and I found something about async.series. I tried something, but it doesn't seem to work, since the result is the same. If the price list file exists, the message 'Prices updated successfully! Lenght:' appears after printing the item price.

function getPrices() {
    console.log("URL requested: ", API_URL)

    restling.get(API_URL).then(function(result) {
        var JSON_Data = result.data

        if (JSON_Data.status == "success") {
            console.log("Prices updated successfully! Lenght: "+JSON_Data.prices.length)
        } else {
            console.log(JSON_Data)
            console.log("An error ocurred during updating prices!")
            return
        }

        fs.writeFileSync("prices/pricelist.txt", JSON.stringify(JSON_Data.prices))
    })
}

function getItemPrice(item) {
    var file = JSON.parse(fs.readFileSync("prices/pricelist.txt"))

    for (var i = 0; i < file.length; i++) {
        if (file[i].item_name == item) {
            return file[i].price
        }
    }
}

function getItem() {
    var item1 = getItemPrice('Sword');
    console.log(item1);
}

async.series([
    function(callback){ 
        getPrices(); 
        callback();
    },
    function(callback){ 
        getItem();
        callback();
    }
]);

EDIT : I've tried something else, but the problem remains the same

async.series([
    function(callback){ 
        getPrices(); 
        callback();
    },
    function(callback){ 
        getItem();
        callback();
    }
], function(error){
    if (error) {
        console.log(error);
    }
});

async.waterfall([
    function(callback){ 
        getPrices(); 
        callback();
    },
    function(arg1, callback){ 
        getItem();
        callback();
    },
], function (error) {
    if (error) {
        console.log(error);
    }
});

Mmm, i think not makes so much sense write the response in a file for read later, since you can use directly the response to find the item, but this should works.

function getPrices(callback) {

  restling.get(API_URL).then(function(result) {
    var JSON_Data = result.data

    if (JSON_Data.status == "success") {
      console.log("Prices updated successfully! Lenght: " + JSON_Data.prices.length)
    } else {
      console.log(JSON_Data)
      console.log("An error ocurred during updating prices!")
      return
    }

    fs.writeFileSync("prices/pricelist.txt", JSON.stringify(JSON_Data.prices))
    callback(null, null);
  });
}


function getItemPrice(item) {
  var file = JSON.parse(fs.readFileSync("prices/pricelist.txt"))

  for (var i = 0; i < file.length; i++) {
    if (file[i].item_name == item) {
      return file[i].price
    }
  }
}


function getItem(callback) {
  var item1 = getItemPrice('Sword');
  callback(null, item1);
}


async.series([ 
  getPrices,
  getItem
], 
function(err, result) {
  if (err) {
    console.log(err);
    return;
  }
  console.log("result", result);
});

I think a promises based approach and manipulating the response directly instead of writing / reading form a file , will be easier to understand.

function getPrices(url) {
  return new Promise( function(resolve) {
    reslint.get(url).then( function(result) {
        var data = result.data;
        if(data.status === "success") {
          console.log(
            "Prices updated successfully! Lenght: ", 
            data.prices.length
          );
          return resolve(data.prices);
        }
        else {
          throw new Error("An error ocurred during updating prices!");
        }
      })
      .catch(function(ex) {
        throw ex;
      });
  }); 
}


function getItemPrice(item, items) {
  for (var i = 0; i < items.length; i++) {
    if (items[i].item_name == item) {
      return items[i].price
    }
  }
}


getPrices("some/url/which/return/prices")
  .then(function(prices) {
    console.log(getItemPrice("Sword", prices));
  })
  .catch(function(err) {
    console.log("some error -->", err);
  });

If I am not mistaken doesn't series expect a final callback.

async.series([
    function(callback){ 
        getPrices(); 
        callback();
    },
    function(callback){ 
        getItem();
        callback();
    }
],
function(error, [callback array]){
});

Where the callback array will contain the result returned from the functions array. Maybe try async.waterfall?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM