Why Is Value Undefined at .Then() Chained to Promise

Why is value undefined at .then() chained to Promise?

Because no Promise or other value is returned 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 returns 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



Leave a reply



Submit