I’m learning Javascript promises and thens, and am confused with this error using Node.js.
I would like dostart() to wait until nonblocking sleep is finished, and then return "Resolved" to the main func when it is done.
I get this error:
dostart().then(value => {
^
TypeError: Cannot read properties of undefined (reading 'then')
Help appreciated 🙂
function nonBlockingSleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function dostart() {
console.log("Hello2");
nonBlockingSleep(2000).then(() => {
console.log("Done");
return Promise.resolve("Resolved");
});
}
dostart().then(value => {
// main func - I'd like console.log to show "Resolved" when dostart() is finished
console.log(value);
})
>Solution :
dostart isn’t async and doesn’t return the promise from then, so you can’t try to consume that promise where you call it.
You have at least a couple of options.
The simple one in this particular case is to return the promise from then:
function nonBlockingSleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function dostart() {
console.log("Hello2");
// *** Return the promise
return nonBlockingSleep(2000).then(() => {
console.log("Done");
// *** There's no need for `Promise.resolve` here, `then`
// _always_ returns a promise, and will use the return value
// here to fulfill it. (If you return a promise instead, it will
// resolve its promise to the promise you return instead of
// fulfilling its promise.)
return "Fulfilled";
});
}
dostart().then((value) => {
// main func - I'd like console.log to show "Resolved" when dostart() is finished
console.log(value);
});
Your other option is to use async/await:
function nonBlockingSleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// *** Make `dostart` an `async` function
async function dostart() {
console.log("Hello2");
// *** `await` the promise from `nonBlockingSleep`
await nonBlockingSleep(2000);
console.log("Done");
// *** Return the fulfillment value for this function's promise
return "Fulfilled";
}
dostart().then((value) => {
// main func - I'd like console.log to show "Resolved" when dostart() is finished
console.log(value);
});
Side note: I changed "Resolved" to "Fulfilled" because we’re fulfilling the promise in that particular case. It’s common, but incorrect, to use "resolve" for "fulfill." It’s true that fulfilling a promise resolves it, but the converse isn’t true — resolving a promise doesn’t always fulfill it. It might leave it pending, or even eventually reject it, if you resolve it to another promise. I’ve written up promise terminology in this blog post.