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:
JavaScript
x
15
15
1
function initialize() {
2
let callback;
3
console.log('intialization');
4
const promise = new Promise(resolve => callback = resolve);
5
6
new Promise(async () => {
7
await callback();
8
await promise;
9
console.log('cleanup');
10
});
11
12
return promise;
13
}
14
initialize().then(() => console.log('execute then'));
15
which gives me the following output in the terminal:
JavaScript
1
5
1
initialization
2
execute then
3
cleanup
4
- Promise {<fulfilled>: undefined}
5
All good so far. However, when we make the callback async, it no longer works.
JavaScript
1
14
14
1
initialize().then(
2
async () => {
3
await new Promise(resolve => {
4
setTimeout(
5
() => {
6
console.log('execute then');
7
resolve();
8
},
9
10000
10
)
11
})
12
}
13
);
14
gives me this output:
JavaScript
1
5
1
initialization
2
cleanup
3
- Promise {<pending>}
4
execute then
5
I would have expected it to look like this:
JavaScript
1
5
1
initialization
2
- Promise {<pending>}
3
execute then
4
cleanup
5
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:
JavaScript
1
19
19
1
const delayMessage = (message, ms) =>
2
new Promise(resolve => setTimeout(() => {
3
console.log(message);
4
resolve();
5
}, ms));
6
7
async function somethingAsync() {
8
console.log('intialization');
9
}
10
11
function initialize(callback) {
12
return somethingAsync()
13
.then(callback)
14
.then(() => {
15
console.log('cleanup');
16
});
17
}
18
const middleOfProcess = () => delayMessage('execute then', 2000);
19
initialize(middleOfProcess);
It works even if there are multiple async steps to do in between, since you can simply chain them together:
JavaScript
1
22
22
1
const delayMessage = (message, ms) =>
2
new Promise(resolve => setTimeout(() => {
3
console.log(message);
4
resolve();
5
}, ms));
6
7
async function somethingAsync() {
8
console.log('intialization');
9
}
10
11
function initialize(callback) {
12
return somethingAsync()
13
.then(callback)
14
.then(() => {
15
console.log('cleanup');
16
});
17
}
18
19
const middleOfProcess = () => delayMessage('execute then1', 2000)
20
.then(() => delayMessage('execute then2', 2000))
21
.then(() => delayMessage('execute then3', 2000));
22
initialize(middleOfProcess);
The same can be done using async/await syntax:
JavaScript
1
22
22
1
const delayMessage = (message, ms) =>
2
new Promise(resolve => setTimeout(() => {
3
console.log(message);
4
resolve();
5
}, ms));
6
7
async function somethingAsync() {
8
console.log('intialization');
9
}
10
11
async function initialize(callback) {
12
await somethingAsync();
13
await callback();
14
console.log('cleanup');
15
}
16
17
const middleOfProcess = async () => {
18
await delayMessage('execute then1', 2000);
19
await delayMessage('execute then2', 2000);
20
await delayMessage('execute then3', 2000);
21
};
22
initialize(middleOfProcess);