Por que o valor é indefinido em .then () encadeado a Promise?

Dado

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"); } }) } doStuff(9) .then(function(data) { console.log(data) // `undefined`, why? }) 

Por que os data undefined em .then() encadeados para doStuff() ?

   

Porque nenhum Promise ou outro valor é return de .then() encadeado para o construtor Promise .

Note que .then() retorna um novo object Promise .

A solução é return um valor ou outra chamada de function que return valor sa ou 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` }); 

O problema estava enfrentando:

 return (new Promise(..)) //the promise we want to return .then(()=>undefined) // the promise were actually returning, which resolves to undefined 

Como você já deve ter percebido, retorna uma nova promise. Isso tem um bom motivo, torna a promise de encadeamento fácil, por exemplo:

 getUser()//an asynchronous action .then(user=>login(user))//then if we get the user,promise to log in .then(token=>console.log("logged in,token is "+token) //then if we logged in, log it .catch(error=>"login failed");//catch all errors from above 

Mas isso também cria a pequena armadilha que estamos enfrentando. A solução poderia estar retornando a promise original e não a nova promise retornada automaticamente por .then (), pois isso é resolvido como indefinido, já que a function dentro não está explicitamente retornando algo:

 //what were doing: Promise.resolve(n*10)//the original promise resolves to n*10 .then(a=>undefined)//the then gets n*10 passed as a, but returns undefined .then(b=>console.log(b));//b will be undefined :0 //what we want: var promise=Promise.resolve(n*10); promise.then(a=>undefined);//a is n*10, this resolves to undefined promise.then(b=>console.log(b));//but this still logs n*10, as its the original promise :) 

Então, como você pode ver, para retornar a promise original, simplesmente a armazenamos em uma variável, então atribuímos a ela um manipulador e ainda temos uma referência à promise original à qual podemos atribuir outros manipuladores (ou retornar).

Em ação:

 function doStuff(n /* `n` is expected to be a number */) { //create a new promise and store it var promise=new Promise(function(resolve, reject) { setTimeout(function() { resolve(n * 10) },1000); }); //add a then handler to this promise promise.then(result=>console.log(result + " is "+result<100?"not":""+" greater than 100")); //return the original one return promise; } doStuff(9).then(function(data) { console.log(data) //not undefined, as original promise }) 

O doStuff está retornando a Promise . Mas, sua última function, then , não está retornando nenhum valor, portanto, os data são undefined .

Em promises, o valor dos argumentos da próxima function é o valor retornado da function anterior.

 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; }) } doStuff(9) .then(function(data) { console.log(data) // `90` }) 

Você não está retornando o resultado do .then () acorrentado à Promessa. Você precisa adicionar o resultado de retorno; para o.

Como seu valor de dados é o valor de retorno do último .then() , seu último .then() não possui um valor de retorno válido.

Assim, você pode adicionar o valor de retorno na última function .then() .