1

I searched for a long time and although there are many questions with similar keywords, none of them share the same intricacies, so let me explain my problem:

I have a function (getProjectData), that has to be called (it is a system wide thing) to get all data from a particular admin section of a cms. My problem comes from a conditional check, where if A one object is blank, where if B, it needs to contain the result of more than 1 ajax calls. The whole data object gets retuned in this function. Code so far:

function getProjectData() {
    var code = "some id";
    var frozen = true;

    var obj = {
        code: code,
        frozen: true,
        localData: "",
    };

    // here is the point where the object gets returned with a black localData 
    // or splits to get a few ajax calls
    if ( !obj.frozen ) return obj;
    else {
        getLocalData ( code ).then( function ( data ) {
            // ideally, here i would make the parent return obj, but this time with added localData data
            obj.localData = data;
            parent.return obj;
        } );
    }
}

function getLocalData ( code ) {
    var promise = new Promise ( function ( resolve, reject ) {
        var apiReq = "apiUrl";
        var chartsReq = "anotherApiUrl";
        var res;

        $.when(
            // api response
            $.ajax({
                url: apiReq + code,
                type: "get",
                success: function ( data ) {
                    return data;
                },
                error: function ( error ) {
                    return error;
                }
            }),
            // another ajax call..
            $.ajax({ ... }),
            // another ajax call..
            $.ajax({ ... })
        ).then(
            function ( a, b, c ) {
                data = {
                    response: a
                    ...... for b and c
                };
                resolve ( data );
            },
            function ( error ) {
                reject ( error );
            }
        );
    } );
    return promise.then(
        function (data) {
            return data;
        },
        function ( error ) {
            console.log ( error );
        }
    );
}

My problem is that since (and i tried with other ways as well..) all the returns are in a function within other functions, there is no way to return the Obj object after the localData has been added.

I might have over-engineered it but i tried many different ways and since the getProjectData is called by a save button and values need to be returned rather than say, appended to the DOM, i am not sure what to do!

I know that in asynchronous requests, the function has to return before the result is available, where we would usually use callbacks, but a callback will not be able to return something. I could use synchronous requests but i know they are going to be deprecated..

Any ideas?

geodeath
  • 351
  • 1
  • 3
  • 15
  • Ask yourself: Where is the callback function called? – Teemu Aug 25 '16 at 17:11
  • You need to return a promise from getProjectData if it needs to be able to asynchronously look up data. There are other ways to do it, but a promise is probably the simplest. – rdubya Aug 25 '16 at 17:22
  • Avoid the [promise constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi Aug 25 '16 at 20:21
  • You **cannot** `parent.return obj;`. Just return another promise! – Bergi Aug 25 '16 at 20:22
  • @Teemu Care to elaborate? No matter where a callback function would be called, it would still be unable to return to the parent function.. – geodeath Aug 26 '16 at 08:38
  • @rdubya, so whatever calls getProjectData needs to handle a promise, not just data... correct? What would other solutions be, thinking that i might be unable to get my hands on that code? – geodeath Aug 26 '16 at 08:39
  • @Bergi I am aware i cannot return to parent, i was just illustrating the issue at hand and ask what other people do in problems like this. To put it simply, when data is coming asynchronously and the result is not "pushed" at that point to a db or to the DOM, but rather, "asked" for, such as getProjectData, is there really a way out? Or the structure needs to change in whatever calls getProjectData no matter what? – geodeath Aug 26 '16 at 08:41
  • @geodeath: Yes, the calling code needs to change no matter what if the called code is asynchronous. – Bergi Aug 26 '16 at 13:36
  • Is this question still live? – Roamer-1888 Oct 01 '16 at 09:09
  • No, right answer really is that the code expecting the return has to handle a promise, so the question is really "wrong" so to say, or impossible to solve unless you change the code expecting the result. – geodeath Oct 04 '16 at 11:50

1 Answers1

0

The correct way to call functions is listed below.

Sincerely I don't understand what you mean saying:

// ideally, here i would make the parent return obj, but this time with added localData data

Using the following way in the parent you should just call:

getProjectData.then(function(obj){ 
 //... do whatever
});

JS:

function getProjectData() {
    var code = "some id";
    var frozen = true;

    var obj = {
        code: code,
        frozen: true,
        localData: "",
    };

    // here is the point where the object gets returned with a black localData 
    // or splits to get a few ajax calls

    return new Promise(function(resolve, reject) {

      if ( !obj.frozen ) 
        resolve(obj);
      else {
        getLocalData ( code ).then( function ( data ) {
            // ideally, here i would make the parent return obj, but this time with added localData data
            obj.localData = data;
            resolve(obj);
        });
     });
    }
}

function getLocalData ( code ) {
    var promise = new Promise ( function ( resolve, reject ) {
        var apiReq = "apiUrl";
        var chartsReq = "anotherApiUrl";
        var res;

        $.when(
            // api response
            $.ajax({
                url: apiReq + code,
                type: "get",
                success: function ( data ) {
                    return data;
                },
                error: function ( error ) {
                    return error;
                }
            }),
            // another ajax call..
            $.ajax({ ... }),
            // another ajax call..
            $.ajax({ ... })
        ).then(
            function ( a, b, c ) {
                data = {
                    response: a
                    ...... for b and c
                };
                resolve ( data );
            },
            function ( error ) {
                reject ( error );
            }
        );
    } );

    return promise;

}
morels
  • 2,095
  • 17
  • 24