Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question (not issue) #83

Open
danielrousseaug opened this issue Sep 22, 2020 · 2 comments
Open

Question (not issue) #83

danielrousseaug opened this issue Sep 22, 2020 · 2 comments
Assignees
Labels

Comments

@danielrousseaug
Copy link

function getInfoByName(title) {
    const thingy = cli.get({
        'name': title
    });

    thingy.then((value) => {
        arr = value;
        console.log(arr);
        return arr;

    });
}

It logs properly but returns undefined. I don't understand why it waits to resolve the promise for console.log but not for return, sorry for the unnecessary issue but I'm desperate.

@worr worr self-assigned this Sep 23, 2020
@worr worr added the question label Sep 23, 2020
@worr
Copy link
Owner

worr commented Sep 23, 2020

This isn't so much an issue with my library, but more a javascript question.

What you pass to then itself is a function. The () => { } is just syntactic sugar for an anonymous function declaration. You could rewrite it as the following:

thingy.then(function(value) {
        const arr = value;
        console.log(arr);
        return arr;
});

When rewritten like this, it becomes clear that the return actually refers to the inner, anonymous function, not the outer function getInfoByName.

In addition, what's important to understand is that then doesn't block. Node runs a big event loop, and when you pass a function to then, it puts it on the event loop, waits until thingy resolves, and then calls the function you passed into then with the return values from the initial promise. In the meantime, getInfoByName has already returned and finished.

Now, if you want to pass along the results of cli.get through getInfoByName, there are a couple of ways that you can accomplish this. Let's go through the options and talk about the upsides and downsides of each.

  1. async/await

We can make getInfoByName and async function, which means that it gets executed asynchronously, and won't return until cli.get has fully resolves. This would look like the following:

async function getInfoByName(title) {
  const arr = await cli.get({ 'name': title });
  return arr;
}

Now, arr is returned from getInfoByName just like originally intended. But, it's important to understand that this doesn't magically make the asynchronous call to cli.get synchronous. It now means that when getInfoByName is called, it too will be executed asynchronously and added to the event loop that node started, so calling code will need to be prepared to call asynchronous code too.

What that means in practice, is getInfoByName will only be callable from normal functions as a promise (and still executed asynchronously) or will only be callable with await from async functions. Some folks refer to this as function coloring due to this popular blog post: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/

  1. Return a Promise

You don't have to use the fancy async/await syntax, and just return a Promise. In that case, you'd now resolve getInfoByName like any other function that returns a Promise: by calling then or catch or whatever on it. This'd look roughly like:

function getInfoByName(title) {
  return cli.get({'name': title});
}

Here, you're just forwarding along the Promise that I returned, and calling code will be able to chain .then calls to extract the data.


Finally, the most important part of this, is that 1 & 2 are the same option. async functions are just syntactic sugar for wrapping your return value in a Promise object if it isn't already a Promise.

Let's look at this trivial jsfiddle: https://jsfiddle.net/cd7x6kvh/

If you look at the js console after running it, you can see that even though we told our function foo to return a simple integer, it's actually returning a Promise. async/await certainly makes it nicer to pretend that it's closer to being synchronous, but that's really just a sweet lie. You're still dealing with Promise objects at the end of the day.

Let me know if that helped or if you have other questions!

@maormagori
Copy link

@worr I found this library today and just wanted to say you taking your time and carefully explaining The async concept to this dude is the most wholesome thing I've seen on github. Big ups to you man!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants