Exsecuting SuiteCRM call synchronously using NodeJs - node.js

I am updating data in SuiteCRM using set entry call. But my issue is that the call is asynchronous and what I want it to be synchronous. My code in node js. Kindly help me out.
CRM.set_entry("Cases",array_to_set_entry[i],function(err1, res1, body1){
console.log("I am inside crm set_entry");
if (body1 && typeof body1.id !== constant.undefined) {
console.log("checkCRM")
}
else {
console.log("checkCRM failed")
} });
I searched stack overflow for solutions. I found async.queue() as a possible solution but still i am not getting how to use it in my case.

Related

Updating a user concurrently in mongoose using model.save() throws error

I am getting a mongoose error when I attempt to update a user field multiple times.
What I want to achieve is to update that user based on some conditions after making an API call to an external resource.
From what I observe, I am hitting both conditions at the same time in the processUser() function
hence, user.save() is getting called almost concurrently and mongoose is not happy about that throwing me this error:
MongooseError [ParallelSaveError]: Can't save() the same doc multiple times in parallel. Document: 5ea1c634c5d4455d76fa4996
I know am guilty and my code is the culprit here because I am a novice. But is there any way I can achieve my desired result without hitting this error? Thanks.
function getLikes(){
var users = [user1, user2, ...userN]
users.forEach((user) => {
processUser(user)
})
}
async function processUser(user){
var result = await makeAPICall(user.url)
// I want to update the user based on the returned value from this call
// I am updating the user using `mongoose save()`
if (result === someCondition) {
user.meta.likes += 1
user.markModified("meta.likes")
try {
await user.save()
return
} catch (error) {
console.log(error)
return
}
} else {
user.meta.likes -= 1
user.markModified("meta.likes")
try {
await user.save()
return
} catch (error) {
console.log(error)
return
}
}
}
setInterval(getLikes, 2000)
There are some issues that need to be addressed in your code.
1) processUser is an asynchronous function. Array.prototype.forEach doesn't respect asynchronous functions as documented here on MDN.
2) setInterval doesn't respect the return value of your function as documented here on MDN, therefore passing a function that returns a promise (async/await) will not behave as intended.
3) setInterval shouldn't be used with functions that could potentially take longer to run than your interval as documented here on MDN in the Usage Section near the bottom of the page.
Hitting an external api for every user every 2 seconds and reacting to the result is going to be problematic under the best of circumstances. I would start by asking myself if this is absolutely the only way to achieve my overall goal.
If it is the only way, you'll probably want to implement your solution using the recursive setTimeout() mentioned at the link in #2 above, or perhaps using an async version of setInterval() there's one on npm here

How to console.log a promisified mongoose query *without* bluebird

I am trying to run a mongoose query and write it to the console without installing yet another library like bluebird. I have been unable to find this in the documentation.
Here is the query:
function activityH(){
return setRecords.find({'item.title': 'marzipan'}
, 'item.title item.quantity').exec();
}
And the context in which I am calling it:
....[a bunch of promises].then(activityF).then(activityG).then(activityH).then(function(doc){console.log(doc);});
All of the prior activities are completing, but nothing is logging even though my query should have results. I feel this is a very basic question but I have looked for hours trying to find a solution and if this is a duplicate, the original answer is very hard to search for!
Do I absolutely need bluebird to do this? E.g. this blog post
Thank you
You could write a little logging function wrapper to help you out. Something like
function log(data) {
console.log(data);
return data;
}
And then add it your Promise chain.
....[a bunch of promises]
.then(log)
.then(activityF)
.then(log)
.then(activityG)
.then(log)
.then(activityH)
.then(log)
If you want some default messaging you could also pass a message string
function log(msg) {
return function(data) {
console.log(msg, data);
return data;
}
}
And then would add to the chain like:
activityA()
.then(log('activityA'))
.then(activityB)
.then(log('activityB'))

Node.js: displaying MongoDB results using response.write(), when to execute response.end()

I'm writing a simple app using Node.js. I use no frameworks (to understand how it works at a "lower" level).
What I'm trying to do:
When a GET request is sent to '/list', I use my MongoDB connection to do a find(). Then I want to iterate over each of the returned items, and display them using response.write("" + myItem).
The problem is that I need to execute a response.end() at the end, and I don't know when "the end" will be -- as all my response.write() statements are executed using callbacks.
Here's my code:
db.items.find({state: "free"}, function(err, myItems) {
if (err) {
console.log("There was an error executing the database query.");
response.end();
return;
}
else if (myItems){
myItems.forEach( function(myItem) {
res.write("<p>" + myItem.title + "</p>\n");
});
}
res.write("</div>");
res.end();
}
I have the feeling I'm missing an idiomatic way to use callbacks here... What's the clean way to fix this?
Thank you!
Thats the correct way, your end() will be called at the end of your callback, so after your foreach loop, the function will go on and send the end() method.
Or maybe did I missed the point of your question. But I think not.

azure node.js request, response - seeking some clarification

I am using Azure Mobile services-NodeJS backend, and when programming it, I always face this doubt - let me explain using the below code snippet
//--------------------------------------------------------------------------
function addUserToDB(request, response){
///some code here
var theUser = request.user;
///get the user's entity object
try {
objAppUser = buildAppUserEntityObj(theUser, request); //for simplicity sake, lets say this is not asynchronous function
}
catch (err) {
console.log ('error in addUserToDB when calling buildAppUserEntityObj'); //****????****
request.respond(statusCodes.BAD_REQUEST, err);
return; // ##????## is a 'return' needed here to avoid the execution of the code below, or should I assume that the function will return once request is responded (request.respond) in above line.
}
....code to add userEntity to DB
//some more code in case of successful try above, can I assume there is no way this code will be reached in case of error in the above try-catch
// ofcourse I can move this code in the 'try' block above, but I am just trying to understand what happens if above try ends in catch block for some reason and there is no 'return' at the end that catch block.
}
//--------------------------------------------------------------------------
function buildAppUserEntityObj(user, request) {
if ( user.level === 'anonymous' ) { //ideally this would be called in above function, but I am putting this here just to throw an example.
console.error('Anonymous User' );
request.respond(statusCodes.BAD_REQUEST, message); //will this request.respond will send the response to client immediately, or will it be passed on as error the try-catch of above 'addUserToDB' function
return; // ##????## also, is 'return' needed here to avoid the execution of the code below,
}
....code to build a User entity object based on some business logic
}
//--------------------------------------------------------------------------
I guess, it all boils down to three questions:
1. Is 'return' needed in the two places (marked by ##????## in the above two functions?
2. Will the message (marked by //****????**** ) be logged in case user.level === 'anonymous'
3. request.respond vs response.send , whats the difference?
I believe these doubts are because of my lack of thorough expressJS knowledge, so while I am going thru azure/express.js documentation again, I thought I would throw my doubt here to the expert community to get a more clear explanation.
Many thanks.
First
In the second return (insode of buildAppUserEntityObj function, I believe you want it to be:
throw new Error("Anonymous user is not allowed")
Otherwise, even if user is anonymous, your catch code will never execute anyway.
You need the first return;, otherwise it will continue executing the code below.
Second
Message will be logged, if you fix the code described in First paragraph.
Third
There is no request.respond in standard Node.js http module. Can you clarify, what module are you using? That module's API shall answer your question anyway.

AngularJS Mongoose error handling

I've build a simple application with AngularJS. Part of this application is calling REST services. For that, I'm using mongoose. Everything works great, but I'd like to better handle errors. A sample code could be :
Express:
DBCollection.find({}, function (err, tuples) {
if (err) {
console.log('Error!');
}
res.send(JSON.stringify(tuples));
});
AngularJS:
DBService.query(function (res) {
$scope.data.lists = res;
});
The problem I'm faced with is as follow. Imagine I've got an error on the mongodb server side. I've got an error, so I log it in the console and then ? What happens on the angularjs/front-end side ? If I send the error as a http response, I suppose angular would interpreate it as the response of the query but with unexpected content and produce an exception ? how to deal with that ?
Angular is like Santa, it knows when responses are bad or good. There are 2 solutions, ones solutions is to create an error handler on each request. The other is to use $httpProvider.interceptors to globally handle errors before they become a problem on an individual request level.
Option 1
DBService.query(function (res) {
scope.data.lists = res;
},function(errorResult){
console.log(errorResult); // <- take a peek in here, find something useful
});
Option 2
$httpProvider.interceptors.push(['$q',function($q) {
return {
'responseError': function(rejection) {
console.log(rejection); // <- take a peek in here, find something useful
return $q.reject(rejection);
}
}
}]);

Resources