5

If you want to execute code after a callback is called in JavaScript, then you can just place it after the callback:

function demoCallback(callback) {
  callback()
  console.log("I execute second")
}

demoCallback(() => {
  console.log("I execute first")
})

Is it possible to do the same thing with an ES6 Promise from within the scope of the function? Let's say I have a function that returns a Promise:

function demoPromise() {
  return new Promise((resolve, reject) => {
    resolve()
    console.log("I execute first")
  })
}

demoPromise().then(() => { console.log("I execute second") })

The Code inserted after resolve executes once the Promise is resolved, but before then is called outside the scope of the function. Is there a way that I can execute code after both, but do so from within the scope of the function?

Hyyan Abo Fakher
  • 3,497
  • 3
  • 21
  • 35
Max K
  • 656
  • 1
  • 6
  • 22
  • 1
    It will still run, but not necessarily before the then. – Get Off My Lawn Jul 23 '18 at 14:24
  • 1
    It's really unclear what you asking here, `resolve` is something you control, you decide when to resolve your promise,.. So in the above if you want `first / second`,. just change the order `console.log("first"); resolve();` – Keith Jul 23 '18 at 14:25
  • You can pass a function to `resolve` and call that function in `then` – Hikmat G. Jul 23 '18 at 14:30
  • @Keith perhaps I bolded the wrong question. I'm asking (specifically) the question that is bolded at the bottom. Can I execute code after the Promise resolves and .then() is called, but from within the scope of the function? – Max K Jul 23 '18 at 14:30

3 Answers3

8

Is it possible to do the same thing with an ES6 Promise from within the scope of the function?

No, this isn't possible. then callbacks always run asynchronously, and that includes being asynchronous in regard to the resolve() call.

(That said, promise callbacks are queued, so you can abuse that queue to get your code behind the other:

function demoPromise() {
  const p = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
      p.then(() => {
        console.log("I execute second");
      }); // because I will be scheduled second
    }, 1000);
  });
  return p;
}

demoPromise().then(() => {
   console.log("I execute first");
}); // because I was scheduled first

But please don't do that)

If you want to execute code after a callback is called in JavaScript

then you probably should not just return a promise. Take a callback that does what you want before executing your code:

function demoPromise(callback) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000);
  }).then(() => {
    return callback();
  }).then(res => {
    console.log("I execute second");
  });
}

demoPromise(() => {
   console.log("I execute first");
}).then(() => {
   console.log("I execute last");
});

This is known as the disposer pattern and very useful for handling resources.

robe007
  • 3,523
  • 4
  • 33
  • 59
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

You can resolve the Promise with a function that can be called in a then block. So long as that function is called within the block, you can execute code before it like so

function demoPromise() {
  return new Promise((resolve, reject) => {
    resolve(function(){
        console.log("I execute second")
    });
  })
}

demoPromise().then(f => { console.log("I execute first");f();})
Max K
  • 656
  • 1
  • 6
  • 22
Hikmat G.
  • 2,591
  • 1
  • 20
  • 40
  • 1
    Sadly, even that little `;f();` is too much code :-) -- the point of a disposer is that it cleans up regardless of what the calling code does; if the caller has to remember to call a callback then Murphy's Law says that sooner or later, they won't. – AlexChaffee Nov 25 '18 at 16:16
0

You could try the following


    demoPromise().then(()=>{
        console.log('I execute first')
    }).then(() =>{
        console.log('I execute second')
    }).catch((err)=>{
        console.error(err)
    }).finally(()=>{
        console.log('I execute last')
    })

Schäfer
  • 181
  • 1
  • 1
  • 7