4

I have an array of urls like this

var urls = ["www.google.com", "www.yahoo.com"];

And I want to loop though the urls and perform an async task inside the loop and not move on to the next item until the async task has finished. I know you can do this with promises but I have having some trouble with it. Here what I have

var xmlReader = require('cloud/xmlreader.js');

function readResponse_async(xlmString) {
    var promise = new Parse.Promise();
    xmlReader.read(xlmString, function (err, res) {
        if(err) {
            promise.reject(err);
        } else {
            promise.resolve(res);
        }
    });
    return promise;
}

for (i = 0; i < urls.length; i++) {

    Parse.Cloud.httpRequest({
        url: unionUrls[i],
    }).then(function(httpResponse) {
            try {
//              console.log(httpResponse.text)
                return readResponse_async(httpResponse.text)
            } catch (e) {console.log(e)}

}

But right now it doesn't wait for the readResponse_async to finish, how can I have it wait for that?

Thanks

EDIT

After reading the response I make a save to my database and I have another array like this

var location = ['USA', 'England'];

And I make the save like this

function saveLoc_async(data, location) {
var i3, i4, i5, m,
            TestItem = Parse.Object.extend("TestItem"),//can be reused within the loops?
            promise = Parse.Promise.as();//resolved promise to start a long .then() chain
        for (i3 = 0; i3 < data.count(); i3++) {
             (function(testItem) {
                        testItem.set("item", data.at(i));
                        testItem.set("location", location);
                        //build the .then() chain
                        promise = promise.then(function() {
                            return testItem.save();
                        });
                    })(new TestItem());
//************************
//CALL  retry(); here?
//**************************

}

Because with your answer I have

function retry() {
if (urlsUnion.length > 0) {
    var nextUrl = urlsUnion.pop();
    //********** ADDED LINE
    var nextLoc = location.pop();

    Parse.Cloud.httpRequest({
        url: nextUrl,
    }).then(function(httpResponse) {
        xmlReader.read(httpResponse.text, function (err, res) {
            if(err) {
                // show an error
            } else {
                //********** ADDED LINE
                saveLoc_async(res, nextLoc);
                retry();
            }
        });
    });
}
}

SO where should retry(); go because right now with the save sometimes it puts the second location with one of the first items url? why would that happen?

6
  • 3
    just to make sure I understand... you wanna use a async call to work as a sync call? The main reason of the async is to allow continue before finish the process of the call! Commented Sep 21, 2015 at 18:15
  • Do you want each URL to execute in isolation and wait until the entire loop body of the other is completed before starting the next iteration? Right now, as written, this will create a promise for each URL right away, and each will complete execution as it's able. Commented Sep 21, 2015 at 18:16
  • Even if you cannot use jQuery, see the answer at this link to get an idea of how to structure your code: stackoverflow.com/questions/20688803/… ...This is assuming what you want is to perform async calls on a list of items, and have the async call finish before going to the next loop item Commented Sep 21, 2015 at 18:16
  • 1
    Promises are all about async - which is what 99% of people want to ensure speed - so they are the opposite of what you need I think Commented Sep 21, 2015 at 18:18
  • @RodrigoGomes yes, because after I read the response I make a save to my Parse database, and I want to wait, this is a background job so I am not worried about speed Commented Sep 21, 2015 at 18:23

3 Answers 3

2

I did something similar to this for an animation.

var actions = [drawXXX, fadeOutYYY, drawXYZ];


this.startAnimation = function () {
    actions.reduce(function (previousAction, nextAction) {
        return previousAction.then(nextAction)
    }, $.when());
}
Sign up to request clarification or add additional context in comments.

Comments

1

Your code fires both urls immediately, and does not wait in-between.

What you would have to do is to remove the first url from the array and fire it. In the 'then' branch check if you still have url's in the array and repeat.

Like this (untested, edited to make the code clean again):

var xmlReader = require('cloud/xmlreader.js');

function readResponse_async(xlmString) {
    xmlReader.read(xlmString, function (err, res) {
        if(err) {
            // show an error
        } else {
            readFirstUrl();
        }
    });
}

function readFirstUrl() {
    if (urlsUnion.length == 0) {
        return;
    }
    var url = urlsUnion.pop();
    Parse.Cloud.httpRequest({
        url: url,
    }).then(function(httpResponse) {
        readResponse_async(httpResponse.text);
    });
}

readFirstUrl();

6 Comments

I added an example in the answer.
nowhere, that's why I called it untested :). Thanks for the tip, I updated the code to include the xml reading.
... however, I think this solution is not simple enough anymore, so I'll reflect that in my answer.
Could you please see the edit about the save after reading the url?
I see it now. The retry should probably best be done in saveLoc_async(res, nextLoc).then(function { retry(); }); but the question has become very complicated now.
|
0

Not sure I understand your use of unionUrls array, but if you have your URL's in a urls array, I think this is pretty clean:

function getUrl(url) {
      return Parse.Cloud.httpRequest(url)
                  .then( function(httpResponse) {
                     return readResponse_async(httpResponse.text);
                  });
}

urls.reduce( function(prev, url) {
   return prev ? prev.then( function() { getUrl(url); }) : getUrl(url);
 }, null);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.