Why is value undefined at .then() chained to Promise?
Because no Promise
or other value is return
ed from .then()
chained to Promise
constructor.
Note that .then()
returns a new Promise
object.
The solution is to return
a value or other function call which return
s a value or Promise
from .then()
.
function doStuff(n /* `n` is expected to be a positive number */) { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(n * 10) }, Math.floor(Math.random() * 1000)) }) .then(function(result) { if (result > 100) { console.log(result + " is greater than 100") } else { console.log(result + " is not greater than 100"); } // `return` `result` or other value here // to avoid `undefined` at chained `.then()` return result })}
doStuff(9).then(function(data) { console.log("data is: " + data) // `data` is not `undefined`});
Weird Promise Chaining Case: then() parameter is undefined, last chain data not returned
console.log(prevBatchResult); // prevBatchResult is undefined, why?
Because the return value of the previous then()
function is return resolve(batchResult);
and the resolve(...)
function returns undefined
.
Your problem is caused by the explicit-construction anti-pattern.
- Remove
return new Promise((resolve, reject) => {
(and the matching});
. - Don't call
resolve
just return the value (batchResult
) you want to resolve the promise with.
Why is promise resolving with undefined?
Because you've chained several promises together and one of your .then()
handlers returns nothing.
This part:
.then((result) => {
console.log('hello');
// since there is no return value here,
// the promise chain's resolved value becomes undefined
});
returns nothing which is essentially the same as return undefined
and therefore the resolved value of the chain becomes undefined
.
You can change it to this to preserve the resolved value:
.then((result) => {
console.log('hello');
return result; // preserve resolved value of the promise chain
});
Remember that the return value of every .then()
handler becomes the resolved value of the chain going forward. No return value makes the resolved value be undefined
.
Promise chaining, this is undefined
Methods are implemented as old-fashioned function
functions, so not as arrow functions, which means this
is determined by the way the methods are called. As you provide a function reference as the then
callback, this
will be undefined
(or the global object in sloppy mode).
There are at least two ways to keep this
as you want it:
initiateAPI(): Promise<any> {
return this.method1()
.then(_ => this.method1())
.then(_ => this.method2())
.catch(console.log);
}
or:
initiateAPI(): Promise<any> {
return this.method1()
.then(this.method1.bind(this))
.then(this.method2.bind(this))
.catch(console.log);
}
Undefined reading in promise chain
console.log returns "undefined" so the solution was to return the employeeData array in the promise chain to pass on.
.then(response => {
if (response.confirmAdd) {
buildTeam()
return employeeData
} else {
return employeeData
}
})
Promise chaining returning undefine
As you pointed out in the comments, GetProjectManager
seems to accept a callback (and return undefined
) rather than returning a Promise.
You can wrap your original callback-based function into a function that returns a promise, and call that instead:
function GetProjectManagerAsync (serviceFactory, projectId) {
return $q(function (resolve, reject) {
serviceFactory.GetProjectManager(projectId, resolve, reject)
})
}
dataFactory.GetProject()
.then(function(result){
return result.Response.ProjectId
})
.then(function (projectId){
return GetProjectManagerAsync(serviceFactory, projectId)
})
.then(function (projectManager) {
// do something neat with `projectManager`
})
.catch(function (error){
throw error // or do real error handling
})
There are also great libraries that will do this for you automatically, like Thenify.
Edit: Thanks Bergi for pointed out that Angular.js promises would make more sense here.
How does Promise chain work when one callback doesn't return any promise?
If the promise chain returns a promise, it will call the next then (or catch) with the resolved (or rejected) value of that promise. If it doesn't, then it'll just call the next then
with the returned value (or undefined
if nothing was returned):
const myPromise = myApiCall().then(response => {
return anotherApiCallThatReturnsAPromise(response);
}).then(secondResponse => {
// this is the resolved value of anotherApiCall...
return secondResponse;
}).catch(err => {
// this error could be because myApiCall failed or because anotherApiCall... failed
})
const myPromise = myApiCall().then(response => {
return 42
}).then(value => {
// value is 42
}).catch(err => {
// this error, if present, is because myApiCall failed
})
Extrapolating, let's return nothing from the first callback:
const myPromise = myApiCall().then(response => {
// notice we do not return anything here
// we just call a function - i.e. return undefined
doSomeWorkAndReturnNothing();
}).then(value => {
// value is undefined because nothing was returned from the previous `then`
}).catch(err => {
// this error, if present, is because myApiCall failed
})
Just for fun, here's what is looks like using await
in an async
function:
const myFunc = async () => {
try {
const response = await myApiCall();
const secondResponse = await anotherApiCallThatReturnsAPromise(response);
return secondResponse;
} catch(err) {
// this error could be because either of the previous two await-ed calls failed
}
}
Related Topics
How to Maintain a Websockets Connection Between Pages
JavaScript - Head, Body or Jquery
Anchor Jumping by Using JavaScript
Image Manipulation and Texture Mapping Using HTML5 Canvas
Why My Show Hide Button Needs Double-Click on First Time
How to Create Checkbox Inside Dropdown
How Does the New Operator Work in JavaScript
Download Canvas as Png in Fabric.Js Giving Network Error
When Is the Comma Operator Useful
Template Does Not Update When Using Ui-Router and Ion-Tabs
How to Detect Element Being Added/Removed from Dom Element
JavaScript to Scroll Long Page to Div
Ignore Mouse Interaction on Overlay Image
Html5 Video Not Streaming and Taking 90 Seconds to Load
Change <Audio> Src with JavaScript
Msie and Addeventlistener Problem in JavaScript
How to Record Webcam and Audio Using Webrtc and a Server-Based Peer Connection