Ignoring exception from a finished function - node.js

I keep getting this error when this function executes.
Ignoring exception from a finished function
What I'm I missing?
exports = module.exports = functions.database.ref('/cards/{userId}/{id}')
.onCreate((snap, context) => {
const token = snap.val().token;
const userId = context.params.userId;
const stripeRef = admin.database().ref('/stripe').child(userId);
return stripeRef.once('value').then(function(snapshot) {
let accountId = snapshot.val().accountId;
return stripe.accounts.createExternalAccount(
accountId,
{ external_account: token },
function(err, card) {
snap.ref.child('cardId').set(card.id);
});
});
});

use try and catch to log the errors manually, like
try {
//code goes here
}
catch(error) {
console.log(error)
}

Related

Callable cloud functions - handle error in android

im trying to delete an user from firestore and from auth.
I have this callable cloud function:
export const deleteUser = functions.https.onCall(async (data, context) => {
const userEmail = data.userEmail;
const collection = data.collection;
try {
deleteUserByEmail(userEmail, collection)
return "deleted!"
} catch (error) {
throw new functions.https.HttpsError('invalid-argument', 'there is no user with that email', error);
}
})
async function deleteUserByEmail(userEmail: string, collection: string) {
const auth = admin.auth();
const db = admin.firestore();
const { uid } = await auth.getUserByEmail(userEmail);
await db.collection(collection)
.doc(uid)
.delete();
await auth.deleteUser(uid);
return uid;
}
in android i have this:
fun deleteFromFirebase(){
val data = hashMapOf(
"userEmail" to user.email,
"collection" to "User"
)
functions // Optional region: .getInstance("europe-west1")
.getHttpsCallable("deleteUser")
.call(data)
.addOnCompleteListener() { task ->
if(!task.isSuccessful)
{
Log.d("User", "ERROR")
val e = task.exception
if (e != null) {
Log.d("Admin", e.message.toString())
}
}else{
Log.d("User", "Deleted")
//make something
}
}
}
If the user in auth and the document nin firestore exist, works great.
But i tryed to generate some error.
So I deleted the user from auth and ran the function. The Android log says D/User: User deleted
but in the console from google cloud:
Function execution took 1878 ms, finished with status code: 200
Exception from a finished function: Error: There is no user record corresponding to the provided identifier.
How can I handle the error and get correctly in android? Thanks!
The deleteUserByEmail function is async and returns a Promise. Your return statement runs before the promises is resolved. Try refactoring the code as shown below:
export const deleteUser = functions.https.onCall(async (data, context) => {
const userEmail = data.userEmail;
const collection = data.collection;
try {
// add await, continues after Promise is resolved
await deleteUserByEmail(userEmail, collection)
return "deleted!"
} catch (error) {
console.log(error) // <-- check for any errors
throw new functions.https.HttpsError('invalid-argument', 'there is no user with that email', error);
}
})
async function deleteUserByEmail(userEmail: string, collection: string) {
const auth = admin.auth();
const db = admin.firestore();
const { uid } = await auth.getUserByEmail(userEmail);
return await Promise.all([
db.collection(collection).doc(uid).delete(),
auth.deleteUser(uid)
])
}

Nodejs exports returns undefined on mongoose Insertion

I have created nodejs application by organising as module structure , The problem I am facing is that a mongodb insertion return undefined value from one of my controller, The issue I found is that my async funtion doesn't wait to complete my mongodb operation But I could not find a solution for that, my route and controller code is given below
route.js
const {
createEvent, editEvent
} = require('./controller');
router.post("/event/create", validateEventManage, isRequestValidated, async(req, res) => {
let data = {};
data.body = req.body;
try{
let event = await createEvent(req.body);
console.log(event) // returned undefined
data.event = event;
res.status(200).json(data);
}catch(error){
console.log(error)
res.status(200).json({error:error});
}
});
controller.js
exports.createEvent = async(data) => {
// return "test" // This works correctly
const eventObj = {
name : data.name,
description : data.desc,
type : data.type,
startDate : new Date()
}
const event = await new Event(eventObj);
await event.save((error,event)=>{
if(error) {
return error;
}
if(event){
return event;
}
});
}
You should not await the new Event constructor.
Also, since you are using async - await you can
remove the callback from the save and try ... catch the error to handle it:
exports.createEvent = async (data) => {
// return "test" // This works correctly
const eventObj = {
name: data.name,
description: data.desc,
type: data.type,
startDate: new Date(),
};
try {
const event = new Event(eventObj);
await event.save();
return event;
} catch (error) {
return error;
}
};

Cannot return array if item not present in dynamodb

I have a function that will take an array of jobs as a parameter in it. This function will check the existence of each job in the database through its id.
If a job is not to present in the database, that particular job needs to be pushed into an array called latestJobs. I'm calling this function in my main.js file. But the code breaks and stops.
Below is my main.js code:
module.exports.app = async () => {
try {
...
const jobs = await getJobsForCountries(body);
const latestJobs = await filterPreDraftedJobs(jobs);
console.log('latestJobs', latestJobs);
} catch (e) {
console.error('Error:- ', e); // Comes to here
}
};
My checker function looks like:
module.exports = async (jobs) => {
let latestJobs = [];
for (const job of jobs) {
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: job.Id
}
};
await dynamoDb.get(params, (err, data) => {
if (err) {
latestJobs.push(job);
console.log('Job not found in DB');
}
}).promise();
}
return latestJobs;
};
How can I fix this issue? I want the latestJobs which will not present in the database. Is there a function for dynamodb which can do this for me?
You are mixing callback, promise and await style. I would do it like this
module.exports = async (jobs) => {
let latestJobs = [];
for (const job of jobs) {
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: job.Id
}
};
try {
const result = await dynamoDb.get(params).promise();
if (result) {
return;
}
} catch(err) {
latestJobs.push(job);
}
}
return latestJobs;
};
Also, make sure that table is created and the region and name you are passing is correct.
I am not much familiar with dynamoDB but looking at the above conversation code must be something like this. I have tried to improve performance and making sure the code is modular and readable.
async function addUpdateJobs(jobs)
{
let paramsArray = [];
for (const job of jobs)
{
const jobParams = {
params:{
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: job.Id
}
},
job:job
};
paramsArray.push(jobParams );
}
return await this.getJobs(paramsArray);
}
function getJobs(paramsArray)
{
let latestJobs = [];
paramsArray.each(async (jobParam)=>
{
try
{
const result = await dynamoDb.get(jobParam.params).promise();
if (result)
{
return;
}
} catch (err)
{
latestJobs.push(jobParam.job);
}
});
return latestJobs;
}
PS: Also I was gonig through error handling in amazondynamodb.

Retrieve the GET query string parameters using Express

I seem to have troubles on getting the query string parameter on my Postman.
First, I wanted to get all of the game types API by using the url of:
localhost:3000/api/gameType/dota2
Here is the code below:
const router = require('express').Router();
const GameTypeRepository = require('../../repository/GameTypeRepository');
router.get('/', async (req, res) => {
try {
const game_types = await GameTypeRepository.findByName(req.query.name);
res.json(game_types);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
GameTypeRepository.js
const BaseRepository = require('../../../shared/repository/BaseRepository');
const GameType = require('../models/GameType');
class GameTypeRepository extends BaseRepository {
constructor(model) {
super(model);
}
findByName(name, fields) {
const options = {
where: { name }
};
if (!!fields && fields) {
options.attributes = fields;
}
return this.model.findOne(options);
}
}
module.exports = new GameTypeRepository(GameType);
But when I execute the url to my Postman, I get this log on my terminal that says:
Executing (default): SELECT `id`, `name`, `description` FROM `game_types` AS `game_types` WHERE `game_types`.`id` = 'dota2';
Which should be 'name' = 'dota2'
Any ideas on how to work with this? TYIA.
I have solved this problem by adding /type in my router.get('/type/:name,
router.get('/type/:name', async (req, res) => {
try {
const game_types = await GameTypeRepository.findByName(req.params.name);
res.json(game_types);
} catch (error) {
res.sendStatus(404);
}
});

Serverless: dynamodb giving error on create record when trying with async/await

I am trying to create a record in dynamodb(Using dynamoose). code is
class Test {
constructor() {
this.table = dynamoose.model(tableName, tableSchema);
}
// userdata object - {
// cusotmerEmail: 'tushar.gaurav+testf40#accionlabs.com',
// customerBusinessName: 'DoogleDnd',
// customerFirstName: 'Tushar',
// customerId: 101211,
// customerLastName: 'Gaurav',
// isDeleted: false,
// sku: '100',
// userId: '5c1776e94bea867c3f896236'
// }
async createUser(userData) {
try {
const res = await this.table.create(userData);
console.log('Update user record - ', res);
return res;
} catch (error) {
throw new Error(error);
}
}
}
*input values to the create function are correct as the same input I tried with batchPut(), it's working.
And even update call to the table is also working.
async updateUser(userData) {
try {
const res = await this.table.update(userData);
console.log('Updated user record - ', res);
return res;
} catch (error) {
throw new Error(error);
}
}
This is the error I am getting -
Error - {"message":"The conditional request failed", "code":"ConditionalCheckFailedException", "statusCode":400}
This is the calling function -
module.exports.subscribeUser = async (event) => {
let inputBody = (typeof event.body === 'object' ? event.body :
JSON.parse(event.body));
inputBody.userId = event.pathParameters.id;
try {
// Validate input
await asisvc.validateInput(inputBody);
inputBody = await UserSvc.constructUserObject(inputBody);
console.log('Constructed object - ', JSON.stringify(inputBody));
const userData = await testObj.createUser(inputBody);
return Utils.buildResp(codes.ok, { userData }, {});
} catch (error) {
console.log(error);
return Utils.buildResp(codes.badrequest, { Error:
Utils.getErrString(error) }, {});
}
};
I tried googling it, but didn't find any proper document.
Thanks in advance.
In Dynamoose by default we check to see if the primary key already exists in the table when using the Model.create method.
So your error:
{"message":"The conditional request failed", "code":"ConditionalCheckFailedException", "statusCode":400}
Indicates that the primary key already exists in the table. So you are trying to create a duplicate item.
In the documentation there is an options property that you can use to allow overriding the object.
For example the following code will allow overrides:
const res = await this.table.create(userData, {overwrite: true});

Resources