Home > Mobile >  Chain functions so that they run once previous is complete
Chain functions so that they run once previous is complete

Time:03-16

I am trying to simply chain some async functions together so they operate in order. I am probably making a basic error.

I just want the printFirst to run and then once complete for printSecond to run.
below is my code that does not work

const printFirst = ()=>{
  console.log('First')
}
const printSecond = ()=>{
  console.log('Second')
}
// Print this first (after 2 sec)
const first = () =>{
  setTimeout(printFirst,2000)
}
// Once the above function is run then run this
const second = () =>{
  setTimeout(printSecond,2000)
}

first()
.then(second())

I get the error

node timeout.js
file:///Users/bob/Documents/dev/javascript/node/nodeScratch/timeout.js:20
.then(second())
^

TypeError: Cannot read properties of undefined (reading 'then')
    at file:///Users/bob/Documents/dev/javascript/node/nodeScratch/timeout.js:20:1
    at ModuleJob.run (node:internal/modules/esm/module_job:195:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:337:24)
    at async loadESM (node:internal/process/esm_loader:88:5)
    at async handleMainPromise (node:internal/modules/run_main:61:12)

I did see a post here How do I access previous promise results in a .then() chain? which suggests that I may not have to use "then". HOwever I am not sure if that is actually relavant to my usecase.

CodePudding user response:

Basic async functions in JS are based around Promises. You can write a Promise that waits for a network response or other IO. You can write one that waits for user interaction. You can also write one that waits for the end of a setTimeout. This is one example of that:

const printFirst = ()=>{
  console.log('First')
}
const printSecond = ()=>{
  console.log('Second')
}
// Print this first (after 2 sec)
const first = () => new Promise ((resolve, reject) => {
  setTimeout(() => resolve(printFirst()), 2000)
})

// Once the above function is run then run this
const second = () =>{
  setTimeout(printSecond,2000)
}

first()
  .then (second)

As well as wrapping your first function in a new Promise call, we also need to switch

first () .then (second ())

to

first () .then (second)

The initial one fires the second function immediately and passes the result of it to .then. Instead, we want to pass the function itself. For more complex needs, you could do this instead:

first () .then (result => second (result, someOtherArgument))

If you want something else to run after second, then it also needs to be wrapped in a Promise.

CodePudding user response:

The first function needs to be async so as to return a promise on which you can then call .then():

const printFirst = () => {
  console.log('First')
}
const printSecond = () => {
  console.log('Second')
}

const first = async() => {
  setTimeout(printFirst, 2000)
}

const second = () => {
  setTimeout(printSecond, 2000)
}

first().then(() => second())

  • Related