0

I want to push an object into array that one of the field is value need to get from async function

function loadContentAsync(url) {
    var deferred = Q.defer();
    request(url, function (err, res, html) {
        if (!err) {
            deffered.resolve(html);
        }
    });
    return deffered.promise;
}

var aList = $('#mCSB_5_container ul').find('a');
console.log(c);

var list = [];
aList.each(function (i, elem) {
    var html = loadContentAsync(this.attribs.href);
    list.push({
        title: $(this).text(),
        url: this.attribs.href,
        content: html
    });
});

But when I run this code, because loadContentAsync function doesn't return value synchronously, the html field will be null.

How can I this field asynchronously?

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
Milad Khajavi
  • 2,769
  • 9
  • 41
  • 66
  • Does loadContentAsync function returns anything normally? – Ubiquitous Developers Aug 21 '15 at 12:00
  • 1
    Most async operations take succes and failure callbacks. Manipulate the async data inside the callback. Or use promises. – Shilly Aug 21 '15 at 12:01
  • Yea loadcontentasync should either return a promise or accept a callback that gets the data. Unfortunately, if you do it wrong, you'll store the data in wrong order – U Avalos Aug 21 '15 at 12:02
  • I've edited my question. my `loadContentAsync` return promise. – Milad Khajavi Aug 21 '15 at 12:06
  • 2
    That's not a correct way to return or resolve a promise I'd say... – deceze Aug 21 '15 at 12:08
  • @deceze so, what it the correct way? – Milad Khajavi Aug 21 '15 at 12:13
  • What kind of promise library are you intending to use? Deferred? Had a look at the examples? https://github.com/medikoo/deferred/blob/master/examples/while-loop.js – deceze Aug 21 '15 at 12:19
  • 1
    @MiladKhajavi: for one thing, your `loadContentAsync` function never initialises `deferred`. See [How do I convert an existing callback API to promises?](http://stackoverflow.com/q/22519784/1048572) on how to fix it. – Bergi Aug 21 '15 at 12:23
  • @WouterHuysentruit You still forgot to call `deferred.reject` when appropriate – Bergi Aug 21 '15 at 12:38

1 Answers1

1

You need to wait for the promises to be resolved. In order to maintain the correct order of the elements, you should use Q.all() to accumulate the results of all the promises:

function loadContentAsync(url) {
    var defer = Q.defer();
    request(url, function (err, res, html) {
        if (err) {
            defer.reject(err);
        }
        else {
            defer.resolve(html);
        }
    });
    return defer.promise;
}

var aList = $('#mCSB_5_container ul').find('a');
console.log(c);

var promises = aList.map(function (i, elem) {
    return loadContentAsync(this.attribs.href);
}).get();

var list = [];
Q.all(promises).then(function (htmlList) {
    htmlList.forEach(function (html) {
        list.push({
            title: $(this).text(),
            url: this.attribs.href,
            content: html
        });
    });
});
Ben
  • 10,056
  • 5
  • 41
  • 42