0

Say, I have a function F1 that will be called in many other function. F1 is meant to return a value VAL that will be used in F2. A promise is needed to retrieve that needed data that will help calculate VAL. Having F1 as a promise would cause a lot of confusion in F2, for F1 is often called inside IF statements and FOR loops. Let me illustrate this scenario:

function F1(param1, param2) {
    var VAL = 0;

    promise(param1, param2).then(function(data) {
        for (var i = 0; i < data.length; i++) {
            // Do some calculation here
        }
    });

    return VAL;
}

function F2(x1, x2) {
    var myArray = [],
        someValue = 0;

    if ([conditional expression]) {
        someValue = F1(x1, x2);

        call_some_function();

        myArray.push({
          val: someValue,
          ...
        });
    }

    var x = someValue + y;

    myArray.push({
        id: x,
        ...
    });

    return myArray;
}

How do I make sure that F1 returns VAL (integer) so I can use it as a synchronous function?

Thanks in advance for your help.

EDIT:

Here is how the code looks like:

    function myFunc(x, y) {
        return init()
            .then(function() {
                return getData(x, y).then(function(data) {
                    if (data.length == 0) return [];

                    var id, name, 
                        firstPass = true,
                        headIn = 0, 
                        headOut = 0, 
                        currentHead = 0,
                        payWtIn = 0,
                        payWtOut = 0,
                        expectedAdg = 0,
                        weight = 0,
                        results = [];

                    for (var i = 0; i < data.length; i++) {
                        if (firstPass) {
                            id = data[i].id();
                            name = data[i].name();
                            headIn = data[i].headIn();
                            headOut = data[i].headOut();
                            expectedAdg = data[i].expectedAdg();
                            firstPass = false;
                        }

                        if (id != data[i].id()) {
                            buildFunc();
                            reset();
                        }

                        headIn += data[i].headIn();
                        headOut += data[i].headOut();
                        payWtIn += data[i].payWtIn();
                        payWtOut += data[i].payWtOut();
                    }

                    buildFunc();

                    return results;



                    function buildFunc() {
                        currentHead = headIn - headOut;

                        var headDays = getHeadDays({ locationId: locationId, groupId: groupId, callDate: null });

                        var totalWeight = headIn != 0
                            ? ((((headDays * expectedAdg) + payWtIn) / headIn) * currentHead) + payWtOut
                            : 0;


                        results.push({
                            id: id,
                            name: name,
                            headIn: headIn,
                            headOut: headOut,
                            headDays: headDays,
                            currentHd: currentHead,
                            totalWt: totalWeight
                        });
                    }

                    function reset() {
                        id = data[i].id();
                        name = data[i].name();
                        headIn = data[i].headIn();
                        headOut = data[i].headOut();
                        expectedAdg = data[i].expectedAdg();
                        payWtIn = 0;
                        payWtOut = 0;
                        weight = 0;
                    }
                });
            });
    }

function getHeadDays(params) {
    var VAL = 0;

    promise(params.a, params.b).then(function(data) {
        for (var i = 0; i < data.length; i++) {
            // Make calculation to determine VAL here                           
        }
    });

    return VAL;
}

The init function loads needed entities in the cache (I'm working with BreezeJs) for querying. The getData function gets raw data that are sorted by id from database, and those data are used to determine the results array. As the data are looped through, as long as the id of each record is the same, headIn, headOut, payWtIn and payWtOut are incremented by the record fields, and when the previous and current id are different, we can calculate totalWeight and push a new record to the results array with the buildFunc function. Inside that buildFunc function, we retrieve the headDays in order to calculate totalWeight. The getHeadDays function will be called in many other functions. Please, let me know if you have any questions. Thanks in advance for your help.

eddylepatio
  • 123
  • 1
  • 1
  • 11
  • 1
    You can't take an async operation and make is synchronous. Instead, you will need to learn how to program with it in asynchronous fashion and promises are a good way to do that. You will want to return a promise from `F1` so the caller of `F1` can then use `.then()` on the promise to know when the operation has completed and what value it returned. – jfriend00 Jan 26 '15 at 23:42
  • Thanks for the prompt reply. I was really hoping I wouldn't read any "can't do" messages, but unfortunately I have to face that fact. Sad but so. :( I guess I'm going to have to make drastic changes on the code. Ugrr! – eddylepatio Jan 27 '15 at 05:03
  • So how do I use promises within FOR loops? Any ideas with actual examples would be welcome. – eddylepatio Jan 27 '15 at 06:17
  • If you show us what you're trying to do in the `for` loop (add code to your question or start a new question), we can advise. "Using a promise in a `for` loop" is too generic a question with many possible meanings and solutions. – jfriend00 Jan 27 '15 at 06:18
  • @jfriend00: I got a preview of the code on the post. Thanks. – eddylepatio Jan 27 '15 at 15:32

1 Answers1

3

You can't.

If you need to return a promise, then that is because the value won't be available until some event happens, and the function will (or at least may) return before then. That's the point of promises.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • And of course, you have to account for broken promises too... *sigh* – Frédéric Hamidi Jan 26 '15 at 23:41
  • Yes, I have been using synchronous functions (promises) for quite some time. I just hoped there could be a way of working this situation out. Unfortunately, that cannot happen... – eddylepatio Jan 27 '15 at 05:06
  • @RipHamilton you can make it **look** async with ES6 generators if you can use regenerator or a similar project in your build step (or only target chrome or firefox or node). – Benjamin Gruenbaum Jan 27 '15 at 10:19