fromNodeCallback callback methods order of defintion - node.js

Im learning bacon.js
i wrote test script like that.
var bacon = require('../nodejs/node_modules/baconjs').Bacon;
function TestClass(URL,port,username,password)
{
this.funcCheck = function( data , rescallback)
{
console.log(" data: " + data);
if(data.length > 4)
{
rescallback(null,data.substring(0, 2));
}
else
{
console.log("Calling callback with error data: " + "error");
rescallback("Too short",null);
}
}
}
var tclass = new TestClass();
var names = ['Geroge','Valentine', 'Oz','Nickolas'];
var results = [];
var read = bacon.fromNodeCallback( tclass.funcCheck, bacon.fromArray(names) )
stream.onValue(function(value)
{
console.log(" onValue " + value);
results.push( value);
});
stream.onError( function(error)
{
console.log(" OnError " + error);
// results.push( err);
});
console.log(" results " + results);
The problem is that onError never get called, despite the fact that "Oz" is less than 4 characters and i know that rescallback get called with 1 parameter that is not null.
I can see log printout.
The other thing is that if i change defition of onError and put it before onValue, onError will be called exactly 1 time, and onValue will never be called.
Im sure im missing something very basic but i dont know what exactly.
What im doing wrong?
Thanks

Related

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client | NodeJS ExpressJS MySQL

I dont know what to say, i think code says everything. i just want to render something and this error appears, but i dont know why. I tried so many solutions from stackoverflow, and others that i couldn't count them all. Im using mysql2 lib. Please help.
router.get("/:link", function(req, res){
connection.query(
"SELECT * FROM yourshort WHERE link = '" + req.params.link + "'",
function (err, result, rows, fields){
Object.keys(result).forEach(function(key) {
var row = result[key];
console.log(row.link)
if(row.link = req.params.link) {
res.send(row.link + row.views + rows.created)
return;
} else {
res.send("URL does not exist")
return;
}
});
});
});
just because you send it in foreach you get that error .
do you want to send it just one time and first item of db ? if yes use this :
router.get("/:link", function (req, res) {
var i = 0;
connection.query(
"SELECT * FROM yourshort WHERE link = '" + req.params.link + "'",
function (err, result, rows, fields) {
Object.keys(result).forEach(function (key) {
var row = result[key];
console.log(row.link)
if (row.link = req.params.link) {
if (i === 0) {
res.send(row.link + row.views + rows.created)
i = 1;
}
} else {
if (i === 0) {
res.send("URL does not exist")
i = 1;
}
}
});
});
});
A service that sends your data. You run into problems when you try to return your data in a loop. The good thing about this is to come back after you get all the result you will get from the loop. You can use asynchronous structure for this. Maybe you can try this.
router.get("/:link", (req, res) => {
let myObject = {};
connection.query(
"SELECT * FROM yourshort WHERE link = '" + req.params.link + "'",
async(err, result, rows, fields) => {
await Object.keys(result).forEach(function(key) {
var row = result[key];
if(row.link = req.params.link) {
myObject[key] = {link: row.link, views: row.views, created: rows.created}
return;
} else {
myObject['error'] = 'URL does not exist';
return;
}
});
await res.send(myObject);
});
});

Express route with param is inconsistent. Is it my code?

So I am working on a social networking project, I added the ability to upload images and an API route that can return image objects from a DB so that I can display them. This was all working fine, then I took a few days break from it (new game came out) and now the API rout isn't working, sort of.
So here is the route:
router.get("/image/all/:id", function(req, res, next) {
console.log("Triggered: Images/all/ID");
Image.find({owner_id: req.params.id}).populate("comments").exec(function(err, images) {
if(err) {
req.flash('error', err.toString());
return next();
} else {
console.log("images API trigger");
res.json(images);
return next();
}
});
});
And here is the ajax call:
$.ajax({url: "/image/all/" + uid, success: function(data) {
for(let i = 0; i < data.length; i++){
let img = "<a class='aPic' href='#' data-toggle='modal' data-target='.view-image-modal' data-id='" + data[i]._id + "'> <img src='" + data[i].thumb + "' class='thumbnail pull-left'></a>";
$('#proBox').append(img);
imageData.push(data[i]);
}
$('.view-image-modal').on('show.bs.modal', function(e) {
var button = $(e.relatedTarget);
var id = button.data('id');
var image;
for(let i = 0; i < imageData.length; i++) {
console.log(imageData[i]._id + " | " + id);
let imId = imageData[i]._id.toString();
if(imId == id){
image = imageData[i];
console.log("Found: " + imageData[i].file);
}
}
let splt = image.file.split(".");
let ext = "." + splt[splt.length - 1];
$('.modal-content img').attr('src', "/images/uploads/" + id + ext);
$('.modal-title').html("Uploaded: " + moment(image.created).format("MM/DD/YYYY"));
$('#imgDesc').val(image.description);
$('#imgEdit-button').attr('data-id', id);
$('#imgDelete-button').attr('data-id', id);
//Update comments section
});
}});
So I get this url: http://127.0.0.1:8080/image/all/5989da1afdc58624a0b10fda
the console gives error 404, if I put this in the address bar i get "Cannot GET ..." however if I add or remove a letter from the id, it returns an array as it is supposed to.
I also tried this in an incognito window to make sure it wasn't a cached file issue or anything like that. Any ideas?
In the code above, when an error occurs, you call next(). If you do that and you do not have an error handler, then you will get a 404. In your error case, return res.json(err) instead of return next() and you might actually see why it is failing.
Alternatively you can add an error handler as your final middleware and call next(err).

Why am I getting SyntaxError: Unexpected identifier?

Sorry for asking such dumb question but I spent some time on this and looked to other similar questions and none of them were helpful
I'm defining a function inside var Tools = module.exports and I have no clue of what is going wrong in this function definition:
getLastNRows: function (whereIsData, DB_info, table, NRows, callback) {
if (whereIsData == "MySQL") {
var queryString = "SELECT timestamp, temp1, temp2, temp3, temp4, level_ice_bank, flow, power, level_change_rate FROM " +
table + " ORDER BY id DESC LIMIT " + NRows + ";";
var connnection = mysql.createConnection(DB_info);
connnection.connect(function(err) {
if (err) {
console.log("Couldn't connect to the required MySQL DB.");
console.log("DID NOT GET LAST " + NRows + " ROWS");
throw err;
}
});
connnection.query(queryString, function (err, rows) {
if (err) {
console.log("DID NOT GET LAST " + NRows + " ROWS");
throw err;
}
Tools.setValue(rows);
Tools.dataArray2Object(Tools.result_arr);
callback();
});
}
else {
console.log("Function doesn't accept this DB service.\n(u still have to improve...)");
return;
}
},
I'm getting:
  getLastNRows: function (whereIsData, DB_info, table, NRows, callback) {
  ^^^^^^^^^^^^
 
SyntaxError: Unexpected identifier
Maybe someone catches the error here?
I assume that's an object, and you've just missed the comma before the first row you posted:
var myMethods = {
foo: function () {}, // < This comma
getLastNRows: function (whereIsData, DB_info, table, NRows, callback) {
...
},
};
When you get syntax errors, it means something is wrong with the syntax (the program doesn't even execute).

Slack API dealing with two API's

I am trying to call a function after getting the response from API calls. Like this
function saveScore(bot,result,message){
getFirstScore(bot,result).then(function(fscore){ //API -1
if(fscore){
getSecondScore(bot,result,null).then(function(sscore){ //API -2
if(fscore && sscore){
var finalScores = "First score is " + fscore + " :innocent:" + "\n Second score is "+ sscore +" :blush: ";
var remindAttachment = util.reminderAttachment("",finalScores);
listAllScores(bot,message,remindAttachment);
}
},function(error){
console.log('sscore error: ' + error);
});
}
},function(error){
console.log('fscore error: ' + error);
});
}
function listAllScores(bot,message,remindAttachment){
sendInstructions = function(response, convo){
convo.say(remindAttachment);
convo.say("Take it to the next level:");
convo.next();
setTimeout(function(){
listScores(bot,message);
},2000);
}
bot.startPrivateConversation(message, sendInstructions);
}
Here, I want to call listScores(bot,message); function after convo.say(remindAttachment);. But right now it is loading listScores(bot,message); first. So, I am setting timeout(not a good approach) for listScores(bot,message); to load after sometime.
Is there any better way to call listScores(bot,message); function after convo.say(remindAttachment);
Edit
function listAllScores(bot,message,remindAttachment){
sendInstructions = function(response, convo){
convo.say(remindAttachment, function(error){
console.log("error ::::::::::::::::::::",error);
if(error!=null) {
listScores(bot,message);
}
});
}
bot.startPrivateConversation(message, sendInstructions);
}
modify this convo.say() function to have callback as a function parameter and then inside that callback call "listScores(bot,message)" function.
like this
convo.say(remindAttachment, function(error) {
if(error!=null) {
listScores(bot,message)
}
})

How can I unit test node.js functions with Mocha?

I am trying to test a function that looks like:
function sendVerifySms(patientId, data) {
var smsNumber = data.smsNumber;
var verifyCode = ((Math.random() * 1000000) | 0).toString();
var sql = "UPDATE [patient]";
sql += " SET phone_sms_verify_code = '" + verifyCode + "',";
// verification must take place within a one hour period
sql += " phone_sms_verify_code_expire = '" + moment.utc().add(1, 'hour').formatSqlDatetime() + "',";
sql += " phone_sms_verified = 0,"
sql += " phone_sms = '" + escapeSql(smsNumber) + "'";
sql += " WHERE id = " + escapeSql(patientId.toString());
return sqlServer.query(sql).then(function(result) {
twilioClient.sendMessage({
to: smsNumber,
from: twilioUser.verifyNumber,
body: verifyCode
}).then(function(res) {
console.log('sent verification');
return verifyCode;
}).fail(function(err) {
console.log('error sending verification');
console.log(err);
return err;
});
}).fail(function(err) {
console.log(err);
return err;
});
}
Easy enough, right? Well, first I need to decide what EXACTLY I'm testing for.
That the sql command matches the format given some data
That the twilioClient.sendMessage has been called.
Here is what I have for my test so far:
var should = require('should');
var methods;
var mockery = require('mockery');
var sinon = require('sinon');
describe('RPC Methods', function() {
before(function() {
mockery.enable();
mockery.registerMock('msnodesql', {
open: function() {
return true;
}
});
mockery.registerMock('../../db/sqlserver', {
query: function() {
return {
then: function() {
return true;
}
}
}
});
methods = require('../../../rpc/methods');
});
it('should send a verify SMS', function() {
var data = {
}
methods.sendVerifySms(1, data);
should(1).equal(1);
});
});
So now I'm a bit lost from here. I have a ton of require and since I want to isolate my individual functions for testing, I figured something like mockery would work. Where do I go from here?
If anything is unclear, please post a comment and I'll clarify.
Thanks!
With mocha tests you have an optional done callback that makes testing async functions easier, like this:
it('should send a verify SMS', function(done) {
var data = {};
var code = 1;
methods.sendVerifySms(code, data)
.then(function(actualCode) {
should(actualCode).equal(code);
done();
});
});
I would also have some feedback to offer on the async function you're testing. First I'd say you don't have to nest promise chains the way you are, and in this case its probably better that you didn't. If you simply return a promise from within a promise callback, you can chain it at the same level, like this:
return sqlServer.query(sql).then(function(result) {
return twilioClient.sendMessage({
to: smsNumber,
from: twilioUser.verifyNumber,
body: verifyCode
});
}).then(function(res) {
console.log('sent verification');
return verifyCode;
}).fail(function(err) {
console.log(err);
throw err;
});
Second, in the error handler you had before you were simply returning the err. This is probably a bad idea because it tells the consumer of your promise that everything is hunky dory and that they should proceed as such. Throwing an error on the other hand will allow that consumer to handle the error however they want in their own .fail block.

Resources