0

I'm learning how Asynchronous JavaScript works, and I'm trying to print to the console the numbers 1 and 2 (in this order). The function that logs 1 has a setTimeout, and as such, the order is always inverted. I know why this happens. I just don't know how to make it work as I would like to. I've tried this:

function first(){
    setTimeout(
            ()=>console.log(1),
            1000
    )

    return Promise.resolve(true)
}

function second(){
    console.log(2)
}


function a(){
    first()
    .then(second())
}

console.log("running...")
a()

and also this:

async function first(){
    setTimeout( 
        ()=>console.log(1),
        2000
    )

    return true            
}

function second(){
    console.log(2)
}


async function a(){
    await first()
    second()
}

console.log("running...")
a()

Both of which print

running...
2
1

The desired output would be

running...
1
2

What am I doing wrong?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Vitor Hugo
  • 25
  • 1
  • 7
  • 1
    You're not doing anything asynchronously. Your first `first` immediately returns a promise resolved to true. To make `setTimeout` into a promise, see [How to make a promise from setTimeout](https://stackoverflow.com/q/22707475/215552) – Heretic Monkey Jun 28 '22 at 17:35
  • 2
    Additionally to what @HereticMonkey said: `.then(second())` -> `.then(second)` – VLAZ Jun 28 '22 at 17:39

3 Answers3

0

Would callbacks not be acceptable?

function first(callback) {
  setTimeout(() => {
    console.log(1);
    callback();
  }, 2000);
}

function second() {
  console.log(2)
}
// When first is completed, second will run.
first(() => second());
console.log("This can run at any time, while we're waiting for our callback.");
BGPHiJACK
  • 1,277
  • 1
  • 8
  • 16
  • Achievable with promises as well. – BGPHiJACK Jun 28 '22 at 17:47
  • I actually also had tried with callback, but in this line ```first(() => second())``` I had ```first(second)```. I don't understand why you're sending a callback as argument, instead of the plain function ```second``` – Vitor Hugo Jun 28 '22 at 17:57
  • oh, and @bgphijack thanks, by the way. I'm still studying which answer I'll take as the right one. – Vitor Hugo Jun 28 '22 at 17:59
0

Read about Js promises (developer.mozilla.org) here his your code working

function first(){
    return new Promise((resolve)=>{
                        console.log('waiting')
                        setTimeout( ()=>{console.log(1); resolve('waiting finished')}, 2000 )
                        }
                      );
                    }

function second(){
    console.log(2)
}


async function a(){
    await first().then(res => console.log(res))
    second()
}

console.log("running...")
a()
z44.nelther
  • 898
  • 5
  • 8
0

Thank you guys for your feedback. I upvoted your answers as they both helped me solve this issue, and helped me get to a higher understanding of the matter at hand (but because I'm still new here, the upvote is just like a Promise).

However, I feel like none of them has gotten to the SPECIFIC point that was causing the issue.

Here's the commented working code

// With Callback, Async and Await

async function first(sec){
     
    await new Promise ( (resolve) =>  setTimeout(()=>{ // this ' (resolve) => ' will make 
                                                       //sure the Promise is pending until 
                                                       // the code reaches the
                                                       // execution of function resolve()
        console.log(1)
        resolve(/* return a value */) 
                    
        /*  so,  ' (resolve) => ' and then the 
            ' resolve( value ) '
            are THE MAIN THING.... "await" will only work if 
            there is a Promise<pending> right in front of it, 
            and in order to do that we have to create
            a Promise object that will receive a resolve() AND/OR reject() as argument
            functions. (or whatever function name we want to use for those parameters).
 
            And when the code fulfills the promise 
            (by reaching either resolve() or reject()) --- in this case, by reaching 
            ' resolve( value ) ', 
            the Promise<pending> will turn to Promise<fulfilled> and this 
            asynchronous part of the code will, then, continue... 
        */ 
                    
        },
        2000
    ))

    sec()
}


function second(){
    console.log(2)
}


console.log("With callback, async, await ...")
first(second)

Now, without callback

// Without Callback, and using .then()

function first(){
     
    return new Promise ( (resolve) =>  setTimeout(()=>{ 
        console.log(1)
        resolve(/* return a value */) 
                    
        },
        2000
    ))
}


function second(){
    console.log(2)
}


console.log("Without callback, and using .then() ...")
first().then(second) // we could also use first().then(()=>second()) if we wanted to
                     // do something with the returned fulfilled Promise/Response object
                     // or if we wanted to send the second() function to the 
                     // callback stack before running it
Vitor Hugo
  • 25
  • 1
  • 7
  • You still seem confused about what `resolve` does. Resolve (optionally) returns a `value` that fulfils the promise (e.g. `resolve(value)` or `resolve()`. That value is passed to the next callback in the promise chain (`.then(value => {})`. The caller will receive it as long as a later callback in the chain doesn't provide its own return value (or undefined). – Dave Meehan Jun 29 '22 at 11:36
  • Your later comments regards wrapping `second` is partially correct, but also that the value provided by `resolve` in `first` is passed as the first argument to `second` when no wrapper is used (even if its the value `undefined`). Essentially, the next callback in the chain receives the return value from the one preceeding it. – Dave Meehan Jun 29 '22 at 11:38
  • Hi, @DaveMeehan thanks for your feedback. Yeah, I understood all that you mentioned, but I assumed you could process data inside the ```resolve()```. Can you only determine a value to be sent? why do you think the last comment is only partially correct? – Vitor Hugo Jun 29 '22 at 15:16
  • See [docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) - you'll see that resolve is a value, but can also be a promise, so it goes into the promise chain ahead of anything else already defined. Maybe that's where you get that you can 'do something'? – Dave Meehan Jun 29 '22 at 15:28
  • "do something with the returned fulfilled promise" - You get the fulfilled value, not a promise. "or if we wanted to send the second() function to the callback stack before running it" - `then(second)` is not the same as `then(()=>second())`, as in the latter you are discarding the fulfilled value. In the former, it would be the first argument to `second`. – Dave Meehan Jun 29 '22 at 15:32