1

I'm doing some reading up on JS Promises to up-skill.

Here's my quandry: Say you want to console.log('we done, bruh!') AFTER your data's come back.

so with a Promise, you might say:

let iWantToLogOut = function() {

    let data = fetch('https://jsonplaceholder.typicode.com/users')

    return new Promise((resolve) => {
        resolve(data)
    })
}

And then resolve that promise like:

iWantToLogOut().then((dataBack) 
=> databack.json())
 .then((json) => {
   console.log('We done, bruh! Look: ', json)         
 })

So that's great. You get your API data back and then we log our msg out.

But isn't it just way easier to go:

   let data = fetch('https://jsonplaceholder.typicode.com/users');
   data ? console.log('we done, bruh!') : null;

I'm probably over-simplifying/missing something (because... well... i'm retarded) but I just want to make sure i'm really understanding Promises first before i move onto Async/Await.

Aid19801
  • 1,175
  • 1
  • 17
  • 30
  • 1
    Of course it's easier with if block! The only problem is that it won't work :( Too bad, right? You also set up `iWantToLogOut` wrong. It should just be `let iWantToLogOut = function() { return fetch('https://jsonplaceholder.typicode.com/users') }` – dfsq Apr 12 '17 at 11:38
  • If you do this then each time you will hit the else part. – Jai Apr 12 '17 at 11:39
  • 1
    @DenisTsoi: Timing has nothing to do with it. And the above would always show `we done, bruh!` as the promise returned by `fetch` is a truthy value. – T.J. Crowder Apr 12 '17 at 11:42
  • I'm assuming fetch is not a promise @T.J.Crowder – Denis Tsoi Apr 12 '17 at 11:45
  • @DenisTsoi: `fetch` isn't a promise, it's a function that returns a promise: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API – T.J. Crowder Apr 12 '17 at 11:53
  • Yes the code is misleading. `Fetch()` returns a promise. It shouldn't just be stored in `let data`. – Aid19801 Apr 12 '17 at 11:55

2 Answers2

8

But isn't it just way easier to go:

let data = fetch('https://jsonplaceholder.typicode.com/users');
data ? console.log('we done, bruh!') : null;

It would be, but it doesn't work. What fetch returns is a promise, not the result of the operation. You can't return the result of an asynchronous process. More: How do I return the response from an asynchronous call?

In the upcoming ES2017 spec, though, we have syntactic sugar around promise consumption which will let you write this:

let data = await fetch('https://jsonplaceholder.typicode.com/users');
// --------^^^^^
console.log('we done, bruh!');

Note we don't even need the conditional, because await converts a promise rejection into an exception.

That code would need to be in an async function, e.g.:

(async function() {
    let data = await fetch(/*...*/);
    // use data here
})();

The JavaScript engines in some browsers already support async/await, but to use it in the wild, you'll want to transpile with Babel or similar.


Note: You've shown

so with a Promise, you might say:

let iWantToLogOut = function() {

    let data = fetch('https://jsonplaceholder.typicode.com/users')

    return new Promise((resolve) => {
        resolve(data)
    })
}

There are a couple of problems with that code:

  1. It never settles the promise you created if the fetch fails.

  2. It calls something data which is not data, it's a promise of data (that's mostly style, but it's misleading).

  3. It exhibits the promise creation anti-pattern. You already have a promise (from fetch), no need to create another.

iWantToLogOut should be simply:

let iWantToLogOut = function() {
    return fetch('https://jsonplaceholder.typicode.com/users');
};

That returns a promise that will be resolved with the data, or of course rejected. Which you'd then consume with promise methods or await (within an async function).

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Interesting re the await vs rejection handling. Will read up on that. Re the _fetch returning a promise_ stuff. Yes, i had to fight the urge to bolt the `.then()` onto it as i'm so used to doing so. I guess that makes sense then. And will look fwd to ES7/Babel'ing these to keep it simpler. @TJCrowder – Aid19801 Apr 12 '17 at 11:50
-1

It is not a matter of easy. Usually network calls should be handle asynchronously(I don't want to the anti-pattern of synchronous AJAX calls). At that point you have few options to handle it:

  1. Callbacks
  2. Promises
  3. Observables

In you code above, when it's synchronous, the fetch should return immediately with a promise that will be resolve to the data only when the server has responded. Only then you can check the data for it's content. Further. Because every promise can be fulfilled or failed, in your then you can have a handler for each instead of using the ternary.

From the latest spec:

Synchronous XMLHttpRequest outside of workers is in the process of being removed from the web platform as it has detrimental effects to the end user’s experience. (This is a long process that takes many years.) Developers must not pass false for the async argument when current global object is a Window object. User agents are strongly encouraged to warn about such usage in developer tools and may experiment with throwing an InvalidAccessError exception when it occurs.

Gabriel Kohen
  • 4,166
  • 4
  • 31
  • 46