I have a function that returns a Promise and inside that Promise I get an object in the resolve.
Here it is the function of my service that works good.
buscarUsuario(email: string){
return new Promise((resolve, reject) => {
this.http.post(`${URL}/user/email`, {email})
.subscribe(resp => {
//console.log(resp['usuario']);
resolve(resp['usuario']);
});
})
}
And then I get the value from the promise in this var:
const getDatos = this.usuarioService.buscarUsuario(this.correoUsuario.value.toString());
And then I call the var to get the value from the resolve and I can't extract that value from there:
var usuario: Usuario;
getDatos.then(usu => {
usuario = usu;
//Here I can see the value
console.log(usuario);
});
//But here I can't see the value
//And it's where I really need to get the value
console.log(usuario);
So, how do I get that value outside the Promise?
Using Promises in Angular is NOT recommended. Angular recommends use of Observable to handle asynchronous operations
Lets Try and change your code to return Observables only
buscarUsuario = (email: string) =>
this.http.post<any>(`${URL}/user/email`, {email}).pipe(
map(resp => resp.usuario as Usuario)
)
Basically the above code returns an Observable<any>(Observable of type any). I have type casted using <any> to transform the result to an Obserable<any>. Next I have use piping to extract the usuario from response
Now we can actually assign this value to a variable...
const getDatos$ = this.usuarioService.buscarUsuario(this.correoUsuario.value.toString());
NOTE: This is an Observable and you will need to subscribe to it
Observable can be assigned like any other property
const usuario: Observable<Usuario> = getDatos$
You cannot get the value outside that function, reason because since you use promise, you need to wait until the promise returns the value, so best possible way is you have do rest of your functionality within promise.then.
getDatos.then(usu => {
//implement your other functionality
});`
Related
I am making a function in nodejs to read a value from the database in Firebase and return it. I read in the that way and get the right value by the console.log(), but when i made the return of the value doesnยดt work properly when i call that function
function test() {
database.ref(sessionId + '/name/').once("value").then((snapshot) => {
var name = snapshot.child("respuesta").val()
console.log(name);
return name;
});
}
If someone could help me. Thanks
You're not returning anything from test, so undefined is being implicitly returned. You can return the promise like this:
function test() {
return database.ref(// everything else is identical
}
Note that this will be returning a promise that resolves to the name, not the name itself. It's impossible to return the name, because that doesn't exist yet. To interact with the eventual value of the promise, you can call .then on the promise:
test().then(name => {
// Put your code that uses the name here
})
Or you can put your code in an async function and await the promise:
async function someFunction() {
const name = await test();
// Put your code that uses the name here
}
I am trying out NestJS for the first time.
The question is simple, when I DO NOT use async await in my controller, I am able to return the data without await as async/await is used in the repository class methods
#Get('/:id')
getMessage(#Param('id') id: string) {
const messageId = id;
// works just fine ๐
const message = this.messagesService.findOne(messageId);
return message;
}
But when I make use of NotFoundException from NEST to make sure if I found the data I am supposed to return, I am forced to use async/await because without it, it considers the message to be always there. Which I am assuming is a Promise.
#Get('/:id')
async getMessage(#Param('id') id: string) {
const messageId = id;
// ๐ await
const message = await this.messagesService.findOne(messageId);
if (!message) {
throw new NotFoundException('Message with ID not found');
}
return message;
}
And if I do not use await, it does not throw an exception.
The question is, why/how does it work in the first example without the use of await
The await keyword returns a Promise. Therefore if you return a Promise you have satisfied the contract of returning a Promise.
I presume that Nest.js repository methods need to return a Promise. You have two choices. Either use the async keyword or return a Promise. In the first example you have returned a Promise so that is why it works.
Note that you don't need to use async if you don't want to. You can always go old school. This is what your first example would be like with the logic to check the message:
#Get('/:id')
getMessage(#Param('id') id: string) {
const messageId = id;
// works just fine ๐
const promise = this.messagesService.findOne(messageId).then((message) => {
if (!message) {
throw new NotFoundException('Message with ID not found');
}
else {
return message;
}
});
return promise;
}
We know that in JS, program runs synchronously and findOne is a webAPI provided by the browser. As it is a webapi it will first send the line
const message = this.messagesService.findOne(messageId);
to the api and will return that function again to stack once all the data is received.
(Assuming you know how the event loop and api works in JS)
In the first function you are not checking the variable message(if it is true or false) you are just returning the value so it will return only if the value is present.
But in second function you are checking the var message, if that line is written without the await it will directly go to the "if" statement even before the data is received from the api(findOne) at that time message var would still be undefined. So once you write await, stack will not go to the next line unless the answer from api is received, and at time your if statement will be checked perfectly.
The answer to your question is in the architecture of nestjs/node itself. If you return a promise (your first case) it resolve it and then returns the value. To get more clear idea about this check jiripospisil on 3 Aug 2018 on this issue.
I'm accessing google API for converting coordinates into detailed objects using node-geocoder library from npmjs. Everything went well and I'm getting the expected object from geocoder API. The problem started the moment when I thought of using the data outside the promise function. I want to use the values outside the promise/async-await function.
Below is the code I've tried, Pls take a look and help me. TIA...
function goecoderPromiseFunction() {
return new Promise(function (resolve, reject) {
geocoder.reverse({ lat: 45.767, lon: 4.833 })
.then(data => {
cityName = data[0].city;
resolve(cityName);
})
.catch(err => {
console.log(err);
});
});
}
async function app() {
var a = await goecoderPromiseFunction();
return a;
}
var a = app();
console.log("a->", a);
I expect the variable "a" should print the city name "Lyon", but it prints
a-> Promise { < pending > }
The promise returned by the app function is never consumed, that is why it remains in a pending state.
Call then on the app function to get the result :
app().then(a => console.log("a->", a));
You can also use async/await :
(async function() {
var a = await app();
console.log("a->", a);
})();
An asynchronous function actually returns a promise that 'resolves' to the function's return value. You are therefore assigning a promise to the value of a. If you are in the global scope, you obviously cannot use async/await so you need to use either a self-executing async function or you need to run
a.then(data => console.log('a->', data));
to get what you are looking for.
Find out more about async functions here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
It prints because console.log("a->", a); runs while promise haven't returned answer for a variable "a"
Note: you haven't used reject function, if there is an error you wont notice and may be that error was the required answer to be carried by variable "a" that's why it still pending i.e still waiting.
For more idea try to use reject function inside the catch block example reject(err)
instead of console it out as you've done
had following code which worked:
let sdk = new SDK({ name: "somevalue"});
module.exports= ()=> {
sdk.dothing();
}
I then needed to change the parameter to use data from an async function:
let asyncfunc = require('asyncfunc');
let sdk = new SDK({ name: (()=>{
return asyncfunc()
.then((data) => {
return data.value
})
});
module.exports= ()=> {
sdk.dothing();
}
Following the change, the call to new SDK is failing because the parameter passed is {} as the asyncFunc promise has not yet resolved.
I'm getting back into node after a year and new to promises. what is the proper way to do this?
As you've found, you can't pass in a promise to something that's expecting a string. You need to wait for the asynchronous operation to complete.
This means that your SDK won't be ready right away, so you have two options:
Change your module so it returns a promise for the needed value. Anyone who needs to use your module would need to use the returned promise.
Example:
let pSdk = asyncFunc()
.then(data => new SDK({ name: data.value }));
module.exports = () => pSdk.then(sdk => sdk.dothing());
Store an sdk value that's not populated immediately. Users of your module can obtain the SDK instance directly, but it might not be ready when they need it.
Example:
let sdk;
asyncFunc()
.then(data => sdk = new SDK({ name: data.value }));
module.exports = () => {
if(!sdk) { throw new Error("The SDK is not ready yet!"); }
return sdk.dothing();
};
if any bit of code, in node, is asynchronous then immediately next bit of code will be executed. it doesn't matter if the asynchronous code is wrapped in promise or not.( For codes wrapped in the promise the compiler will return a pending promise to be resoled or rejected and proceed to the next bit of code.) When you are creating an object using new SDK({ }) the name is having reference to a pending promise which is yet to be settled that's why your code is failing to fulfill your requirement. You can do it this way to resolve your problem.
asyncfunc()
.then((data) => {
return new SDK({ name: data.value });
}).then(function(sdk){
//do your work here using sdk
})
One important point to be noted here is you can't return from .then() to assign the value to any variable as you are doing. The value returned from .then() will be accessible from the next chained .then() not by outside global variable.Since you are exporting sdk.dothing() so you need to export it inside the last .then()
I have a function,
asdf() {
var a = fooController.getOrCreateFooByBar(param);
console.log("tryna do thing");
console.log(a); //undefined
if (!a.property) {
//blah
}
that dies. getOrCreateFooByBar does a
Model.find({phoneNumber : number}).exec()
.then(function(users) {})
and finds or creates the model, returning it at the end:
.then(function(foo) { return foo}
How can I use the result of this in asdf()? I feel like this is a fairly easy question but I am getting stuck. If I try to do a.exec() or a.then() I get 'a cannot read property of undefined' error.
The main idea about Promises (as opposed to passed callbacks) is that they are actual objects you can pass around and return.
fooController.getOrCreateFooByBar would need to return the Promise it gets from Model.find() (after all of the processing done on it). Then, you'll be able to access it in a in your asdf function.
In turn, asdf() should also return a Promise, which would make asdf() thenable as well. As long as you keep returning Promises from asynchronous functions, you can keep chaining them.
// mock, you should use the real one
const Model = { find() { return Promise.resolve('foo'); } };
function badExample() {
Model.find().then(value => doStuff(value));
}
function goodExample() {
return Model.find().then(value => doStuff(value));
}
function asdf() {
var a = badExample();
var b = goodExample();
// a.then(whatever); // error, a is undefined because badExample doesn't return anything
return b.then(whatever); // works, and asdf can be chained because it returns a promise!
}
asdf().then(valueAfterWhatever => doStuff(valueAfterWhatever));