Not getting a result after async firebase "set( )" function - javascript

I do not get any result after I run the "set( )" function to the "res" variable when running this code, meaning that the "res" variable is undefined even though the docuement gets created in firebase. I have tried .then() .catch() too and that doesn't give me any kind of result either. The document gets created and everything works, and I if I want I can just return the Promise no matter the outcome of the firebase function, but that feels like it's bad practice since Im overlooking a possible error right?
Can I somehow get a result from "set( )" function? or in some other way make sure that the "set( )" function is successful?
exports.create = async function(listId, name, link) {
const newLinkRef = db.firestore.collection('links').doc();
const data = {
id: newLinkRef.id,
listId: listId,
name: name,
link: link
};
var res = await newLinkRef.set(data);
console.log(res)
if (res.id) {
return new Promise(resolve => {resolve({error: null, linkId: res.Id})})
} else {
return new Promise(resolve => {resolve({error: "Error creating lint"})})
}
}
(I use the "set( )" function over the "add( )" funciton since I want to save the random created Id inside the object stored to, and this was the simplest way I could find to do that)

set() returns a promise, but your use of await consume that promise and leaves res as the result that the promise wraps, which is void. So undefined seems correct there.
I think you're looking for:
try {
var res = await newLinkRef.set(data);
return {error: null, linkId: newLinkRef.Id};
}
catch (e) {
return {error: "Error creating lint"}
}
Alternatively you can not use await, and you end up with:
return newLinkRef.set(data).then(() => {
return {error: null, linkId: newLinkRef.Id};
}).catch (e) => {
return {error: "Error creating lint"}
})

Related

How to map nested array in javascript(node.js) API?

let getOeReport = async (req, res) => {
try {
let searchFormatForReason = {
"query": {
"reasonCode": null,
},
"fields": {
'reason': 1, '_id': 0
}
}
let result = await oeDao.getOeReport(searchFormat)
let resultReasons =
result.map(async res =>
res.sequences.map(inter =>
inter.interrupts.map((interrupts) => {
searchFormatForReason.query.reasonCode = interrupts.reason
reasonDao.getReasonByFields(searchFormatForReason)
})
)
)
console.log(resultReasons)
res.status(200).json({
status: "Success",
data: {
result: result
}
});
} catch (err) {
console.log(err)
res.status(400).json({
status: "Failure"
});
}
};
Here in the above code, If I try to console the resultReasons means I'm getting null. Result variable has nested array of objects so that, I need 'reason' value inside interrupts array which is inside sequences array and that is within the result array. And i should make API request with that value and I could push it into resultReasons array. Please someone help me... Thank You
let resultReasons =
result.map(async res =>
res.sequences.map(inter =>
inter.interrupts.map((interrupts) => {
searchFormatForReason.query.reasonCode = interrupts.reason
reasonDao.getReasonByFields(searchFormatForReason)
})
)
)
In this piece of your code you are using async so you must be receiving a Promise, since you are not making use of await within that async function I don't see the reason of keeping it, however you can just add an await as per the code below and should fix the issue (you are already using async on getOeReport so it will work without any modifications)
let resultReasons =
await result.map(async res =>
res.sequences.map(inter =>
inter.interrupts.map((interrupts) => {
searchFormatForReason.query.reasonCode = interrupts.reason
reasonDao.getReasonByFields(searchFormatForReason)
})
)
)
But you are saying you get null which I don't understand how you are getting it, this because again you are using an async function within the first map, hence you must get a Promise, the only way I see your variable can be null is if the result variable is null, BUT it should trigger an Exception so your console.log will never be excecuted

Properties on awaited variable storing an object showing as undefined

I am trying to use some data that I get back from my mongodb atlas database and then use that data to perform another query. The calling function, selectGoalsForEpic(), calls and awaits findEpic(id). From the console.log statement I have in findEpic, I know that a valid object was found. My console.log statement after findEpic() call even shows [object Object] was returned and not undefined. I'm not sure why js doesn't allow you to view the contents of this variable here but that is beyond the scope of this question I guess. Anyway my next console statement says that epic.goals is undefined and my next query results in an error because of this. I thought await was supposed to pause execution and get the return value from a resolved promise but that doesn't appear to be the case here. Can someplease please explain to me what is going on here? Thanks
export const selectGoalsForEpic= async (id:string) => {
console.log("id is " + id);
const epic = await findEpic(id);
console.log("here epic" + epic);
console.log("EPIC " + epic.goals);
const goals = goalsCollection.find({_id:{$in: epic.goals}})
.toArray()
.then(res => {
return res;
})
.catch(err => {
console.log(`${FIND_EPIC_RESULT}: ${err}`);
});
return goals;
};
export const findEpic = (id:string):any => {
const epic = epicCollection.find({_id:{$oid: id}})
.toArray()
.then(res => {
console.log(res);
return res;
})
.catch(err => {
console.log(`${FIND_EPIC_RESULT}: ${err}`);
});
return epic;
};
// somewhere else calls
selectGoalsForEpic(my_id)
Use console.log("here epic", epic); so that doesn't display [object Object]. That will give you indications on why epic.goals is undefined

IF statement with javascript promise .then()

I am playing around with React recently. I have a axios post function in my callback function.
I am able to get my data from promise then(). My code is something like below:
export const upload = (user, history) => async dispatch => {
const { fileBase } = user;
getBase64(user.fileBase, function (result) {
const query = `query{test( test:"test") { success }}`;
const finalQuery = JSON.stringify(getBody(query, { ip: result }));})))
getRes(finalQuery, function (res) {
res.then(function (result) {
// i am able to access the data through console.dir(result.data.data)
// when i using code below it hits error
// if(result.data.data.login.success) -> it return to me the data is null, even the console.dir is null too.
}, function (err) {
console.log("err: " + err);
});
});
});
};
function getRes(finalquery, cb) {
console.log("finalquery: " + finalquery);
cb(axios.post(API_URL, finalquery));
}
Picture below is my object structure from promise.
I have gone through a lot of reference through only, but I do not see anyone having if statement by checking the result data from promise.
Is it possible for me to check the promise data value and do something in promise then()? if yes, how? if no, why and how?

How to return value from a promise that's inside another function?

I know that a lot of questions have been asked about async programming and Promises, but I really need an example with this specific code to figure out how I should go about returning promises that's being returned in another function.
I have two functions. The first one is called upon GET'ing to a route. This route should create a payment link and save a booking to a database.
exports.create_booking = function(req, res) {
req.body.payment = exports.create_booking_payment(req.body.total_amount);
console.log(req.body.payment); // This returns ' Promise { <pending> } '
var new_booking = new Booking(req.body);
new_booking.save(function(err, booking) {
if (err)
res.send(err);
res.json(booking);
});
};
However creating the payment link happens with an asynchronous method. My first problem was that I could only access the payment inside the methods callback function.
Now I have wrapped the method inside another (async) method in which a Promise is created and resolved. This method is being returned to my first method with an await statement, but all this returns is: ' Promise { } '.
I know that this happens because the method is being returned before the promise is resolved. But I don't understand why this is. My assumption is that the 'await' statement makes sure to wait returning the method before the async function is completed.
exports.create_booking_payment = async function() {
function asyncPayment() {
return new Promise (function(resolve, reject) {
mollie.payments.create({
amount: 20.00,
description: "Reservation code: ",
redirectUrl: "https://www.website.com/",
webhookUrl: ""
}, function(payment) {
if (payment.error) reject(payment.error)
else { resolve({
id: payment.id,
link: payment.getPaymentUrl(),
status: payment.status
})
}
});
});
}
return await asyncPayment();
}
I hope someone can help me out here...
You seem to have missed that an async function still returns a promise, not the actual value. So, when you call create_booking_payment(), you are getting back a promise that you need to use either .then() with or await with. There's no free lunch across a function boundary. await allows you to program in a synchronous-like fashion inside a function, but still does not allow you to return the value from the function. When it looks like you're returning the value from the async function, you're actually returning a promise that resolves to that value.
So, you'd do this with async and await:
exports.create_booking = async function(req, res) {
try{
req.body.payment = await exports.create_booking_payment(req.body.total_amount);
console.log(req.body.payment);
var new_booking = new Booking(req.body);
new_booking.save(function(err, booking) {
if (err)
res.status(500).send(err);
else
res.json(booking);
});
} catch(e) {
res.status(500).send(err);
}
};
or this with .then():
exports.create_booking = function(req, res) {
exports.create_booking_payment(req.body.total_amount).then(payment => {
console.log(payment);
req.body.payment = payment;
var new_booking = new Booking(req.body);
new_booking.save(function(err, booking) {
if (err)
res.status(500).send(err);
else
res.json(booking);
});
}).catch(err => {
res.status(500).send(err);
});
};
Note, I also added more complete error handling to both scenarios. Also, this code would be a lot cleaner if you "promisfied" or used an already promisified interface for your .save() method. I strongly dislike using plain callback async code inside of promise-based code because it ends up duplicating error handling (like you see in this case).
Also, create_booking_payment() doesn't need to be async or use await since all you need it to do is to return your promise which it already knows how to do:
exports.create_booking_payment = function() {
return new Promise (function(resolve, reject) {
mollie.payments.create({
amount: 20.00,
description: "Reservation code: ",
redirectUrl: "https://www.website.com/",
webhookUrl: ""
}, function(payment) {
if (payment.error) reject(payment.error)
else { resolve({
id: payment.id,
link: payment.getPaymentUrl(),
status: payment.status
})
}
});
});
}

Meteor method call returns undefined on the client but not on the server

UPDATE
I just realized something fundamentally wrong in this approach and that nested callbacks can't return something to its parent callback. I came in late in the JS world and come from the Promises era and didn't know this is the problem with callbacks. But I didn't see enough examples for Meteor using promises so I used callbacks instead. However, if this code can be improved I'd appreciate it greatly.
Question
So I'm calling a method from the client using:
Meteor.call('cart.useProfileAddress', {}, (error, address) => {
console.info('Address', address) // this returns undefined on client
})
This is the method in my api/carts/cartsMethod.js
export const useProfileAddress = new ValidatedMethod({
name: 'cart.useProfileAddress',
validate(args) {
//
},
run(args) {
const person = Persons.findOne({'userId': Meteor.userId()});
// If I do the return here I get the address in the browser as defined.
// return person.address
// I'm calling another method under here:
getClosestStore.call({address: person.address}, (error, result) => {
// And another one method call here:
updateCartAddress.call({address: person.address}, (error, result) => {
// So once all the callbacks are done return the address here.
// However the problem is I get `undefined` on the client.
if (!error) {
// console displays something on the Server but is `undefined` on the Client
console.info('Returning Address', person.address)
return person.address
}
})
})
}
})
What could be the problem on the code above? Could it be because I'm trying to get the value from a nested callback?
Also does anyone know how to avoid these nested callbacks? I know how to do it on Node using promises but in Meteor (I'm using 1.4) I'm still clueless.
Methods can run synchronously on server so you do not need to use callback. Result of method will be returned after execution or exception will be thrown if error occurs. Try this:
export const useProfileAddress = new ValidatedMethod({
// ...
run(args) {
const person = Persons.findOne({'userId': Meteor.userId()});
const result1 = getClosestStore.call({address: person.address});
// use result1 if you need to
const result2 = updateCartAddress.call({address: person.address});
// // use result2 if you need to
return person.address;
}
})
This is how I solved my problem using Promise and the new async/await feature of Meteor 1.3+
export const useProfileAddress = new ValidatedMethod({
name: 'cart.useProfileAddress',
validate(args) {
//
},
run(args) {
return ((async () => {
const person = Persons.findOne({'userId': Meteor.userId()});
const storeId = await getClosestStore.callPromise({address: person.address})
const newAddress = await updateCartAddress.callPromise({address: person.address})
return newAddress
})())
}
})
Inside each method I used the didericis:callpromise-mixin so that it will return a promise.

Categories

Resources