1

I'm using the async module's forEachOf method to print the end result after iterating through an object. Here is a shortened version of what I'm doing:

var async = require('async'),
    cheerio = require('cheerio'),
    request = require('request');

var returnArray = [];

async.forEachOf(myObj, function (value, key, callback) {
    var anotherObj = {};

    anotherObj.type = "val1";

    request(someurl, function(err, res, body) {
        if (err) {
            return callback(err);
        }

        var $ = cheerio.load(body);

        anotherObj.name = "val2";

        var miniObj = {};
        $('#some-element', "#an-id").each(function(i, value) {
            var val = value.value;
            miniObj[size] = val;
        });

        anotherObj.miniObj = miniObj;

        returnArray.push(anotherObj);

        return callback();
    });
}, function (err) {
    if (err) {
        console.error(err.message);
    }

    console.log(returnArray);
});

However, when I run the program, nothing (namely, 'returnArray') gets printed to the console like it should be.

For reference, I have looked at these other, similar posts:

I'm not sure what I'm doing wrong here. Could anyone please point out what I'm doing wrong?

Thanks!

EDIT: So I think I finally figured out what I was doing wrong. In a different example I provided earlier HERE, using Runnable I forgot to add a 'return callback()' statement. Then it worked. The only difference between that and this example being that my 'return callback()' statement in the above-provided example is itself called within another asynchronous method. I think in order to fix my problem I will somehow have to make sure (probably using some control flow function in async's library) to call 'return callback()' at the correct 'scope/level' after the second asynchronous method has finished. I think I will attribute this, my mistake, to the lack of documentation on proper usage of the 'return callback()' statement in the async docs. I will update this post with a solution once I figure it out (and catch up on some sleep)!

Community
  • 1
  • 1
youngrrrr
  • 3,044
  • 3
  • 25
  • 42
  • `returnObject` vs `returnArray`? – robertklep Jun 28 '15 at 07:21
  • Oops! That was just a typo. – youngrrrr Jun 28 '15 at 07:21
  • What's the structure of your myObj object? Are you sure you should not be using 'async.each' instead? – Luis Delgado Jun 28 '15 at 10:16
  • @LuisDelgado - I printed myObj to the console before and I'm absolutely certain it takes the form of a typical object in javascript. I also know for a fact that anotherObj is being correctly constructed since when I put a log statement for it in the forEachOf loop, I get what I expect to be printed to the console. – youngrrrr Jun 28 '15 at 18:26
  • @youngrrrr, ok, I see. As a personal note, I have not had so far success in having async work nicely with a function that has an internal callback-async function itself. For those cases, I have resorted to use something like async.waterfall. Your async function has an internal async call using request. Have you tried to architect the code so that your async function does not have nested async calls? – Luis Delgado Jun 28 '15 at 19:10
  • @LuisDelgado - hey, thanks for your reply. I haven't tried that yet as I had hoped there would be an easy solution to this problem of mine. Guess not. I will try asking another forum with help on this issue as I believe removing the nested async calls would be problematic, and I'd like to save it as a last resort. Thanks for your advice though – youngrrrr Jun 28 '15 at 20:15
  • There is nothing wrong with using nested async functions. I'm doing it with my code. You just have to call the inner callback function inside the nested async function. – toshiomagic Jul 27 '15 at 15:54

1 Answers1

-2

Your statement:

if (err) {
    return callback(err);
}

is not valid for asynchronous programming. Instead, you should do:

if(err) callback(err);

This is why you aren't getting anything returned. I rewrote your code with async concepts applied:

var async = require('async'),
var cheerio = require('cheerio'),
var request = require('request');

var returnArray = [];
async.forEachOf(myObj, function (value, key, next) {
    var anotherObj = {};

    anotherObj.type = "val1";

    request(someurl, function(err, res, body) {
        if (err) next(err);

        var $ = cheerio.load(body);

        anotherObj.name = "val2";

        var miniObj = {};
        async.each($('#some-element', "#an-id"), function (value, next) {
          var val = value.value;
          miniObj[size] = val;
        });

        anotherObj.miniObj = miniObj;

        returnArray.push(anotherObj);

        next();
    });
}, function (err) {
    if (err) console.error(err.message);

    console.log(returnArray);
    callback(returnArray);

});

Notice that you have two different named callbacks. The outer function callback is called callback. The inner function callback is called next.

toshiomagic
  • 1,335
  • 1
  • 12
  • 39
  • 2
    This is absolutely wrong. It is advised to use return callback in case the callback is not your last statement in your function in which case you will get "callback got called twice" error. – derek Nov 12 '15 at 20:40