0

I have a Cloud Code function that will execute n times the same block. The block consist in an http call with auth header. to make things simple, I have created a function at the root of my main.js. The function needs to return a result and keep in memory the authData (in order to reuse it for future calls).

function requestURI (uri){
    var authData; // gets generated if null, should be reused if not null
    var result; // supposingly contains the results

    return something();
}

The function something() is a Parse.Promise because I need my calls to be asynchronous. As I understand I can't attach the result nor the authData to my promise.... If I run a console.log() within the function requestURI(), I see authData and result correctly populated as expected

Then I want this function from a Parse function. (the whole purpose is to have the function being re-usable by any other)

Parse.Cloud.define("testCall", function(request, response) {
    var uri1 = '...';
    var uri2 = '...';
    var uri3 = '...';

    return requestURI(uri1).then(function(){
        // how do I get the result of my request?
        return request(uri2);
    }).then(function(){
        // how do I get the result of my request?
        return request(uri3);
    });
}

The problem I have is that I can't retrieve my result out of the requestURI function and it seems that authData is reset everytime I run the function

I read the solution lies in closures but I can't get my head around them...

edit: add the function something():

 return Parse.Cloud.httpRequest({
        method: 'GET',
        url: url,
        headers: {
            "Authorization" : digestAuthHeader
        },
        success: function(httpResponse) {
            // all went well, let's increase the nonceCount, for future calls
            authData["nc"] += 1;
            // I need to return the result object in a promise
            result = httpResponse.data;
            // return a Promise that can be handled by any function
            return Parse.Promise.as(result)); // this promise doesn't work
        },
        error: function(httpResponse) {
            console.error('Request failed with response code ' + httpResponse.status);
            return (null,Parse.Promise.error(httpResponse.text));
        }
    });

edit: here is what I'm trying

// authData is not null, we can make an authenticated call
function makeAuthenticatedRequest(){
    // generate the appropriate auth Header;
    var digestAuthHeader = generateDigestAuthHeader();

    return Parse.Cloud.httpRequest({
        method: 'GET',
        url: url,
        headers: {
            "Authorization" : digestAuthHeader
        }}).then(function(httpResponse) {
            // all went well, let's increase the nonceCount, for future calls
            authData["nc"] += 1;
            // create the final object to return in a promise
            result = httpResponse.data;

            console.log(result) // returns something not null!!!

            // return a Promise that can be handled by any function
            return promise.resolve({'authData': authData, 'result': result});
        },
        function(error) {
            console.error('Request failed with response code ' + error.status);
            return (null,Parse.Promise.error(error));
        });
}


Parse.Cloud.define("testCall", function(request, response) {
    var uri1 = '...';
    var authData;


    return apiCall1001Menus(authData,uri1).then(function(result){
        response.success(result); // returns {}
    });

});

my response callback is {}!!! which is not what I would expect at all

Stephane Maarek
  • 5,202
  • 9
  • 46
  • 87
  • 1
    possible duplicate of [How to return the response from an Ajax call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – Alexis King Dec 29 '14 at 19:35
  • I know how to handle asynchronous call (as outlined above, using promise). My issue is returning data alongside – Stephane Maarek Dec 29 '14 at 19:40
  • Just return the result, and the result will pass to next `then` as the `argument`. If you could explain more about the relation between `result` and `something()` in function `requestURI` then I could give a workaround. – eth3lbert Dec 29 '14 at 20:27
  • 1
    The function as the `then` callback has a parameter - so it should be `.then(function(result){` and you can access `result` – Benjamin Gruenbaum Dec 29 '14 at 20:35
  • @Benjamin Gruenbaum correct. – eth3lbert Dec 29 '14 at 20:38
  • See edit for my something() function. The problem is that I need to increment an integer on a success call, and after that, I can't recreate a Parse Promise that contains data! – Stephane Maarek Dec 29 '14 at 20:41
  • 1
    `Parse.Cloud.httpResponse` actually return promise, so you could write it in promises fashion(`then(...)`). If you prefer call back style then return a non resolved promise, and call `promise.resolve(result)` when you get the result or `promise.reject(error)` when error happen. – eth3lbert Dec 29 '14 at 20:51
  • I am a little confused. Parse.Promise.as(object) doesn't work for me (object) (I can't retrieve object in the then callback. Isn't promise.resolve equivalent? – Stephane Maarek Dec 29 '14 at 21:06
  • look at my attempt to fix the issue above, and maybe it will better explain it? – Stephane Maarek Dec 29 '14 at 21:20

1 Answers1

1

I will give you an example to prevent my bad english cause misleading.

The following rewrite function makeAuthenticatedRequest() in callback deferred antipattern and promise fashion.

Callback:

Deferred antipattern:

function makeAuthenticatedRequest(){
    // generate the appropriate auth Header;
    var digestAuthHeader = generateDigestAuthHeader();
    var promise = new Parse.promise();
    Parse.Cloud.httpRequest({
        method: 'GET',
        url: url,
        headers: {
            "Authorization" : digestAuthHeader
        },
        success: function(httpResponse) {
            // all went well, let's increase the nonceCount, for future calls
            authData["nc"] += 1;
            // create the final object to return in a promise
            result = httpResponse.data;

            console.log(result) // returns something not null!!!

            // return a Promise that can be handled by any function
            promise.resolve({'authData': authData, 'result': result});
        },
        error: function(error) {
            console.error('Request failed with response code ' + error.status);
            // it could be promise.resolve (success) or promise.reject (error)
            promise.reject(error);
        }
    });
    return promise;
}

Promise:

function makeAuthenticatedRequest(){
    // generate the appropriate auth Header;
    var digestAuthHeader = generateDigestAuthHeader();

    return Parse.Cloud.httpRequest({
            method: 'GET',
            url: url,
            headers: {
                "Authorization" : digestAuthHeader
            }
        }).then(function(httpResponse) {
            // all went well, let's increase the nonceCount, for future calls
            authData["nc"] += 1;
            // create the final object to return in a promise
            result = httpResponse.data;

            console.log(result) // returns something not null!!!

            // return a Promise that can be handled by any function
            return {'authData': authData, 'result': result};
        }, function(error) {
            console.error('Request failed with response code ' + error.status);
            return Parse.Promise.error(error);
        });
}
Community
  • 1
  • 1
eth3lbert
  • 813
  • 5
  • 5