1

I have a service that calls a $http request and returns a JSONP . The returned JSONP from the API is either {valid:true} or {valid:false}. My code is:

    this.checkValid = function () {
    return $http({
        method: 'JSONP',
        url: 'API' + '?callback=JSON_CALLBACK',
    }).then(function (response) {
        var temp = response.data.valid;
        return temp; //returns true or false


    }, function (response) {
        console.log('something   went wrong');
    })
}

I have another service that depends on the response returned from checkValid():

                var data = requestService.checkValid();
                var valid;
                //handling the promise
                data.then(function (response) {
                    valid = response;
                    console.log('Inside the then block : ' + valid);
                });

                if (valid)
                    console.log('Valid!');
                else
                    console.log('Not Valid!');

The output is (after the api returns valid:true) :

'Not valid'
'Not valid'
'Not valid'
'Not valid'
'Inside the then block : true'
'Inside the then block : true'
'Inside the then block : true'
'Inside the then block : true'

I would like to know how to wait for the then() to complete, setting value to true or false, then going to the if statement.

Electry
  • 11
  • 1
  • 2

1 Answers1

2

You can never return a value from asynchronous function.

            data.then(function (response) {
                valid = response;
                console.log('Inside the then block : ' + valid);
            });

valid = response is asynchronous (it will be executed when then is triggered). You cannot use this value outside that context (i.e. in your if). If you need to use the response, use it right there in the then function, or return a promise, and continue processing with another then.

Community
  • 1
  • 1
Amadan
  • 191,408
  • 23
  • 240
  • 301
  • async/await is a solution. there are multiple transforms in babel that convert async_/await calls to ES5 -- so it is plainly possible. – roberto tomás May 07 '17 at 18:38
  • @robertotomás: `async/await` is a syntactic sugar for promises (which is exactly how babel converts them into ES5), so I do not think I have said anything incorrect. Besides, consider when the answer was written - `async/await` were not in any specification yet. They still aren't; they are planned for ES2018. – Amadan May 07 '17 at 19:23
  • where you said "You can **never** return a value from asynchronous function." (emphasis mine), you were incorrect. async/await _is_ syntactic sugar -- or rather, really it is standard ES6 -- but the babel polyfill and plugin-async-to-promises for example, converts that syntax to standard CJS. So it seems to be possible. I didn't vote you down or anything, btw. I basically agree with you. Just noting that some form of transform is generalizable. – roberto tomás May 07 '17 at 19:56
  • @robertotomás: We seem to interpret "return" differently. As I said, an `async` function returns a Promise, always, not a "returned" value: `const f = async function() { return 17; }; console.log(f());` gives `Promise`, not `17`; and is thus covered by "... or return a promise..." in the answer. – Amadan May 07 '17 at 23:42
  • no, we have no disagreement about the keyword `return`. You are confusing `async/await` with just `async` by itself. he wants to know how to modify a function so an _inner codepoint_ in the function returns immediately. this is the purpose of `await` in an `async/await` function. such that: `let foo = async asAPromise() => await bar()` will assign the result of `bar()` to `foo` immediately .. I am not sure but I believe `async` flags the parent function of the async section of code that must be refactored and `await` flags the actual code to convert to blocking form – roberto tomás May 08 '17 at 03:29
  • @robertotomás: No parent function marking goes on, and refactoring is not a part of the [draft specification](https://tc39.github.io/ecma262/#sec-async-function-definitions). I am not confusing anything; you seem to be confusing babel operation with language definition. `async` is dead easy: it wraps the function into a promise-returning function (and marks that function as async, which changes its grammar rules and constructor). `await`, when inside `async`-marked function, will accept *any* promise (such as one returned by an async function, but *any* promise will do), and linearise it. – Amadan May 08 '17 at 04:20
  • @robertotomás: One can talk about `async` and `await` separately, though of course they cooperate well. Here's the other side of the equation, `await`-ing a bare promise, instead of another `async`'d function: `z = async function() { let p = new Promise((good, bad) => good(17)); return await p; }; z().then(x => console.log(x))`. The fact remains, `async` function [returns a promise](https://tc39.github.io/ecma262/#sec-async-function-definitions-EvaluateBody). – Amadan May 08 '17 at 04:25
  • Im going to stop responding in this thread since this is clearly becoming an argument to you. I was not responding to your use of `async/await`, you were responding to my use of `async/await` .. where I clearly said it can be converted to commonJS, such as with babel, and therefor an in-line return should be possible, even if the code points involved are more than just the one active code point. Let's just chill, I'm not into arguing over word choice. – roberto tomás May 08 '17 at 12:57