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);