Skip to content
Advertisement

Perform an action after a promise.then callback

I’m trying to encapsulate some intialization / clean up code in a single Promise. What I want if to execute some code, execute the then and then execute some more code. This is what I came up with:

function initialize() {
    let callback;
    console.log('intialization');
    const promise = new Promise(resolve => callback = resolve);

    new Promise(async () => {
        await callback();
        await promise;
        console.log('cleanup');
    });

    return promise;
}
initialize().then(() => console.log('execute then'));

which gives me the following output in the terminal:

initialization
execute then
cleanup
- Promise {<fulfilled>: undefined}

All good so far. However, when we make the callback async, it no longer works.

initialize().then(
    async () => {
        await new Promise(resolve => {
            setTimeout(
                () => {
                    console.log('execute then');
                    resolve();
                },
                10000
            )
        })
    }
);

gives me this output:

initialization
cleanup
- Promise {<pending>}
execute then

I would have expected it to look like this:

initialization
- Promise {<pending>}
execute then
cleanup

How can I fix this? Is this even possible at all?

Advertisement

Answer

You can accept a callback that defines an asynchronous operation. Then it can be inserted into the middle of an promise chain:

const delayMessage = (message, ms) =>
  new Promise(resolve => setTimeout(() => {
    console.log(message);
    resolve();
  }, ms));

async function somethingAsync() {
  console.log('intialization');
}

function initialize(callback) {
  return somethingAsync()
    .then(callback)
    .then(() => {
      console.log('cleanup');
    });
}
const middleOfProcess = () => delayMessage('execute then', 2000);
initialize(middleOfProcess);

It works even if there are multiple async steps to do in between, since you can simply chain them together:

const delayMessage = (message, ms) =>
  new Promise(resolve => setTimeout(() => {
    console.log(message);
    resolve();
  }, ms));

async function somethingAsync() {
  console.log('intialization');
}

function initialize(callback) {
  return somethingAsync()
    .then(callback)
    .then(() => {
      console.log('cleanup');
    });
}

const middleOfProcess = () => delayMessage('execute then1', 2000)
  .then(() => delayMessage('execute then2', 2000))
  .then(() => delayMessage('execute then3', 2000));
initialize(middleOfProcess);

The same can be done using async/await syntax:

const delayMessage = (message, ms) =>
  new Promise(resolve => setTimeout(() => {
    console.log(message);
    resolve();
  }, ms));

async function somethingAsync() {
  console.log('intialization');
}

async function initialize(callback) {
  await somethingAsync();
  await callback();
  console.log('cleanup');
}

const middleOfProcess = async () => {
  await delayMessage('execute then1', 2000);
  await delayMessage('execute then2', 2000);
  await delayMessage('execute then3', 2000);
};
initialize(middleOfProcess);
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement