async not waiting for await in callback to finish - javascript

Im still a rookie with async and awaits, but this is what Im working with.
async function _getImageURLs(folder) {
if (!id) return;
foo.AWSS3Helper.GetImageUrls(so, function (imageUrls) {
return await imageUrls;
});
}
The fuction _getImageURLs() is still returning without waiting for the AWSS3Helper.GetImageUrls finishes. Im guessing it has something to do with being inside a callback function. Does the callback need to be async as well?

Use await on the function not on the return statement
async function _getImageURLs(folder) {
if (!id) return;
foo.AWSS3Helper.GetImageUrls(so, await function (imageUrls) {
return imageUrls;
});
}

As far as i see there are no promises here, you have a callback based mechanism on the api so using async/await seems pointless
you should pass a callback to the method and invoking it as soon as you have the result available
function _getImageURLs(folder, callback) {
if (!id) callback();
foo.AWSS3Helper.GetImageUrls(so, function (imageUrls) {
callback(imageUrls);
});
}
_getImageURLs("somefolder", function(result) {
console.log(result);
// do whatever you want here with the result
};

Try it with observables. Something like this...
function _getImageURLs(folder) {
if (!id) return;
const imageUrlObservable = of(foo.AWSS3Helper
.GetImageUrls(so, function (imageUrls) {
return imageUrls;
})
);
imageUrlObservable.subscribe({
next(imageUrL) { console.log(imageUrL) },
complete() { console.log('Finished sequence'); }
});
}

Related

Loopback findone function

I am using loopback on server side of my application , to fetch and validate a data from database I'm using findOne method which is having a callback function. I wanted to get run the callback function as soon as the findone function is executed, The code i have written is working but i want to avoid usage of async-await. Any other alternative for this?
What I tried
function validId(req) {
const filter = {
where: {
ID: req.id,
}
};
//
const result = await model.findOne(filter);
if (result) {
return true;
} else {
return false;
}
}
module.exports = function () {
return async function validateTenant(req, res, next) {
var id = false;
if (req.url.includes("XYZ")) {
id = await validId(req)
}
//
if (id || !req.url.includes("XYZ")") {
next();
} else {
res.writeHead(404, { "Content-Type": "text/html" });
var html = fs.readFileSync(
"error.html"
);
res.end(html);
}
};
};
you could use the .then() function of the promise
model.findOne(filter).then((result)=>{
//execute the rest of the function that need to be executed after the findOne.
});
// The code will continue to execute while model.findOne is doing it's thing.
But if you want to wait for the FindOne to give a result without using await or the .then it is not possible unless you make a wrapper of findOne or your BDD package have a synchrone findOne

Function returns before completing her job

I've written this function, and it returns the values, before doing her job. So the return is allways undefined. How can I get the right results?
The code:
async function isReachable(hostname, port) {
net
.connect(port, hostname, () => {
console.log(true);
return true;
})
.on('error', () => {
console.log(false);
return false;
});
}
The log:
Promise { undefined }
true
Thank you :)
Change the start of your method to this:
async function isReachable(hostname, port) {
return net
.connect(
...
You're missing the return, and you're getting the default undefined return.
isReachable will then return a Promise that you can await for the result
If net.connect() doesn't return a Promise you will need to wrap the function implementation in a Promise and use the resolve() callback to return true/false within the .connect() and .on() callback functions.
function isReachable(hostname, port) {
return new Promise(
(resolve, reject) => {
net
.connect(port, hostname, () => {
resolve(true);
})
.on('error', () => {
resolve(false);
});
}
);
}
If net returns a promise, the correct solution, for me, should contain 'async' accros of 'await'. Take a look at the doc:
The advantage of an async function only becomes apparent when you combine it with the await keyword. await only works inside async functions within regular JavaScript code, however it can be used on its own with JavaScript modules.
await can be put in front of any async promise-based function to pause your code on that line until the promise fulfills, then return the resulting value.
Something like this:
async function isReachable(hostname, port) {
return netResults = await net
.connect(port, hostname, () => {
console.log(true);
return true;
})
.on('error', () => {
console.log(false);
return false;
});
}

Mongoose function logs correct data but using async function to get it returns undefined

I am trying to query some data from a database and return it to a function. The issue I am having is that when I log the results from the query it is working but when I try to query what the function is returning I am getting undefined. It could be that my async function with mongoose isn't exactly set up correctly. Or maybe I just have the wrong idea of what is happening as I am new to the idea of asynchronous programming.
async function returnBlogThumbnails(filter = "recent", callback){
console.log("returning blogs")
//For now simply filter by most recent
if(filter === "recent"){
Blog.find({}).sort('-date').exec((err,docs) => {
return docs;
});
}
}
and the function that calls this function
app.get('/', (req, res)=> {
console.log("go home");
//Call out to query the database then use async function to return
database.returnBlogThumbnails().then((blogs) => {
console.log(blogs);
//res.render('home', blogs);
});
});
As I have said the console.log spits out what I am looking for. However, the function calling the function with the query always shows undefined. Thanks
The problem is you defined your function with callback and trying to call it as a promise. Your function with promise should be:
async function returnBlogThumbnails(filter = "recent") {
return new Promise((resolve, reject) => { // creates a promise
console.log("returning blogs")
//For now simply filter by most recent
if (filter === "recent") {
Blog.find({}).sort('-date').exec((err, docs) => {
if (err) {
reject(err);
} else {
resolve(docs)
}
});
}
});
}
and then in your route you can call it as:
app.get('/', (req, res) => {
console.log("go home");
//Call out to query the database then use async function to return
database.returnBlogThumbnails()
.then((blogs) => {
console.log(blogs);
// do something with blogs
})
.catch((err) => {
console.log(err);
// handle error
});
});

Angular2 - Promise inside a conditional statement

I need to wait an answer from my server to say if the email is already taken or not. But I'm struggling to make this synchronously. In my if statement, typescript says that isCorrectEmail() is a void function (that I can understand but cannot solve). Any idea?
isEmailAvailable(){
return new Promise( (resolve, reject) => {
this.authService.checkemail(this.user.email).then(result => {
let res = <any> result;
if (res.code == 0){
resolve(true);
}
elseĀ resolve(false);
}, (err) => {
reject(false);
});
});
};
isCorrectEmail(){
this.isEmailAvailable().then( (result) => { return result ; } );
};
checkPersonalInfos()
{
if ( this.isCorrectEmail() == true){...}
..
}
You cannot turn an asynchronous call into a synchronous one.
You have two options: move the code which needs the use the resulting value entirely inside a then callback:
checkPersonalInfos()
{
this.isEmailAvailable().then(isAvailable => {
if (isAvailable) { ... }
}
}
Or use the async/await syntax to make it look like synchronous code, but remember it is still asynchronous so other code will run during the await and if you return a result from the function it will be wrapped inside a Promise():
async checkPersonalInfos()
{
if (await this.isEmailAvailable()) { ... }
...
}
You don't actually need your isCorrectEmail() function here as it does nothing at all to the result, but if it did something more complex so it was actually needed then it has to return the Promise:
isCorrectEmail(): Promise<boolean> {
return this.isEmailAvailable().then(result => result);
};

ES6 generator functions in angular

recently I started using generators in my angular project. Here's how I do it so far:
function loadPosts(skip) {
return $rootScope.spawn(function *() {
try {
let promise = yield User.findAll();
$timeout(function () {
// handle the user list
});
} catch (err) {
// handle err
}
});
}
From what I've read the next part won't be necessary in es7, but currently I have the spawn function in the run block of my app.
$rootScope.spawn = function (generatorFunc) {
function continuer(verb, arg) {
var result;
try {
result = generator[verb](arg);
} catch (err) {
return Promise.reject(err);
}
if (result.done) {
return result.value;
} else {
return Promise.resolve(result.value).then(onFulfilled, onRejected);
}
}
var generator = generatorFunc();
var onFulfilled = continuer.bind(continuer, "next");
var onRejected = continuer.bind(continuer, "throw");
return onFulfilled();
};
Everything works find the way I do it at the moment, the only thing I really don't like is that I have to call $timeout() after each promise. If I don't my $scope variables initialized inside the timeout won't be initialized. It seems to me that angular digest system needs to be triggered manually.
Why is that and is there a way to make this cleaner?
I would assume it is because your spawn method uses native Promises, not the angular implementation. Try to use $q instead:
function continuer(verb, arg) {
var result;
try {
result = generator[verb](arg);
} catch (err) {
return $q.reject(err);
}
if (result.done) {
return result.value;
} else {
return $q.resolve(result.value).then(onFulfilled, onRejected);
}
}

Categories

Resources