Asynchronous calls with AngularJS and Node.js - angularjs

New to AngularJS and Node.js. Please advise.
Because the data I want to display on the page takes quite some time to load. I decide to load the fast data from database_1 first, and then get the slow response from database_2 later. Here is my AngularJS:
var app = angular.module('myApp', [
]);
app.factory('rateFactory', function ($http) {
return $http.get("localhost/rate"); // api or node.js to return only issueId and rate
})
app.controller('SignupController', function ($scope, $http, $filter, rateFactory) {
// Display most of the content first
$scope.showData = function () {
$http.get("localhost/signup") // api or node.js
.success(function (response) {
$scope.Signups = response;
$scope.curPage = 0;
$scope.pageSize = 25;
$scope.numberOfPages = function () {
return Math.ceil($scope.Signups.length / $scope.pageSize);
};
})
.error(function (data, status, headers, config) {
alert(status);
});
}
// Display slow response, Rate, later based on the issueId
$scope.showRate = function (issueId) {
rateFactory
.success(function (data) {
document.getElementById(issueId).innerHTML = data.find(x => x.IssueID === issueId).Rate;
})
.error(function (data, status, headers, config) {
//alert(status);
});
}
});
I wonder whether there is any better way to do it. This my first question.
Next question is about Node.js. If I get the data from ashx or api, it returns the data without any problem. But when using Node.js for both calls, it's a hit and miss. Sometimes it works fine, but most of the time, the 2nd call fails. Am I doing something wrong? Both returns the data perfectly if calling individually. Here is the node.js code:
var express = require('express');
var http = require('http');
var app = express();
var usp2Json = require('./lib/usp2Json.js');
app.get('/iisnode/myApp/signup', function(req, res) {
usp2Json.getJsonFromStoredProc('stroedprocToGetSignup', req, res);
});
app.get('/iisnode/myApp/rate', function(req, res) {
usp2Json.getJsonFromStoredProc('stroedprocToGetRate', req, res);
})
var server = http.createServer(app);
var port = process.env.PORT || 593;
server = app.listen(port, function() {
console.log('Server is running...');
});
usp2Json.js is a custom module to get data from SQL Server with a stored procedures:
exports.getJsonFromStoredProc = function(storedproc, req, res) {
var sql = require("mssql");
var express = require('express');
var app = express();
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
// config database
var config = {
user: 'username',
password: 'password',
server: 'servername',
database: 'databasename',
};
// connect to database
sql.connect(config, function(err) {
if(err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query(storedproc, function(err, recordset) {
if(err)
console.log(err);
// send records as a response
res.send(recordset);
});
});
}

One suggestion I have is to get rid of:
document.getElementById(issueId).innerHTML = data.find(x => x.IssueID === issueId).Rate;
And use regular Angular 2 way data binding, and bind your #issueId element to a $scope.issueId scope variable, and update the scope variable on call success. The way it is done right now is sort of an anti-pattern.
In terms of the NodeJS API call, you will need to show us what the route handler i.e. usp2Json.getJsonFromStoredProc does in it's code. Otherwise your code looks perfectly fine

In terms of the NodeJS API call, the issue is actually the SQL Server connection. When I looked at console.log, it doesn't give me enough information, but simply says "Server is running". I had to add a line to get the details of error:
request.query(storedproc, function (err, recordset) {
if (err) {
fs.appendFile("path"+ datetime+".txt", time + " Error on executing " + storedproc + " - " + err + " \r\n")
//throw (err);
}
// send records as a response
res.send(recordset);
});
This gives me "ConnectionError: Connection is closed.". With this information, I was able to find the solution from here:
https://github.com/patriksimek/node-mssql/issues/138
and answer from Stackoverflow: How can I use a single mssql connection pool across several routes in an Express 4 web application?

Related

How to set up API server for multiple fetch requests of SQL Server data?

I'm new to react, and I want to set up an API server to get SQL Server data, and I want to send multiple fetch requests to the API server.
I've tried the promise.all method, but it's always failing on the second fetch request. The only way I could make it work is by nesting the requests through.then, but I prefer not to, since the number of fetch requests are varied.
Here's my code:
Promise.all([
//the number of requests varied
fetch('http://localhost:8080/api/report/favorite/check/1/1').then(value => value.json()),
fetch('http://localhost:8080/api/report/favorite/check/1/4').then(value => value.json())
])
.then((value) => {
//I always get EALREADYCONNECTING error here from 2nd request and on
console.log(value)
})
.catch((err) => {
console.log(err);
});
Does the problem lie in the API server configuration?
//Initializing node modules
var express = require("express");
var bodyParser = require("body-parser");
var sql = require("mssql");
var app = express();
// Body Parser Middleware
app.use(bodyParser.json());
//CORS Middleware
app.use(function (req, res, next) {
//Enabling CORS
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, contentType,Content-Type, Accept, Authorization");
next();
});
//Setting up server
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
var connPool = new sql.ConnectionPool({
user: 'someuser',
password: 'somepassword',
server: 'some\\thing',
database: 'somedb',
port: 12345
});
//Function to connect to database and execute query
var executeQuery = function(res, query){
connPool.connect().then(function () {
// create request object
var request = new sql.Request(connPool);
// query to the database
request.query(query).then(function (recordset) {
res.send(recordset)
connPool.close();
})
.catch(function (err) {
console.log("Error while querying database :- " + err);
res.send(err)
connPool.close();
});
})
.catch(function (err) {
console.log("Error while connecting database :- " + err);
res.send(err);
});
}
//GET API
app.get("/api/report/favorite/check/:userid/:reportid", function(req, res){
var query = "EXEC rpt.proc_ReportFavoriteCheck " + req.params.userid + ", " + req.params.reportid;
executeQuery (res, query);
});
I tried several methods, as described here, but I can't make it work:
Fetch API requesting multiple get requests
Multiple fetch requests with setState in React
How to finish Fetch data completely and assign it to component state before proceeding further in componentDidMount React?
Solved this by changing my API server configuration:
var executeQuery = async function(res, query){
const pool = new sql.ConnectionPool(dbConfig);
pool.on('error', err => {
console.log('sql errors ', err);
});
try {
await pool.connect();
let result = await pool.request().query(query);
console.log('success')
res.send(result);
return {success: result};
} catch (err) {
console.log('error')
console.log(err)
res.send(err);
return {err: err};
} finally {
pool.close();
}
}

Why does the script get stuck on the connection in this nodejs script

I am using the following from http://www.tutorialsteacher.com/nodejs/access-sql-server-in-nodejs:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
user: 'sa',
password: 'mypassword',
server: 'localhost',
database: 'SchoolDB'
};
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select * from Student', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});
});
});
var server = app.listen(5000, function () {
console.log('Server is running..');
});
When I run this file in Browser, the first time the page runs. But if I refresh it, it says the connection is not open. When I run this outside of the webserver context, it never exits the sql.connect function and needs to be stopped with Control-C in Node. Does anyone know why this code gets stuck in the sql.connect function?
First: The example you where using are based on version 2.3 of node-mssql. The current version ist now 4.1. One recommended way of using node-mssql is using connectionPools. I adapted your code to use pools.
Second: If there is an error, in your code you never reach the point res.send(). So I modified your code to send somethig back in case of an error.
One more hint: I would place the dependency at the top of your app (not within the route)... it will work either way, but your code gets a little bit more clear.
'use strict';
const express = require('express');
const app = express();
const sql = require("mssql");
// config for your database
const config = {
user: 'sa',
password: 'mypassword',
server: 'localhost',
database: 'SchoolDB',
options: {
encrypt: false
},
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000
}
};
// create a connection pool
const pool = new sql.ConnectionPool(config, err => {
if (err) {
console.log(err);
}
});
app.get('/', function (req, res) {
// create Request object (using the connection pool)
const request = new sql.Request(pool);
// query to the database and get the records
request.query('select * from Student', (err, recordset) => {
if (err) {
console.log(err);
res.send(err);
} else {
// send records as a response
res.send(recordset);
}
});
});
var server = app.listen(5000, function () {
console.log('Server is running..');
});
Hope that helps (code above is not tested ...)

Post SQL data to Angular View with NodeJS

I'm having a difficult time posting data retrieved from a server using mysql with node. I have connected to my db successfully, and I can return the data I want by console logging it to the CLI when running "node server.js". However, I'm not sure how to post this data to my Angular view. No problem console logging, but this doesn't help me get data to the application.
For the moment, I'm just trying to get the data to index.html, which is my primary view and holds my ng-view portion for Angular routing. I'm probably missing something obvious bc I'm new to NodeJS.
// MODULES
var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
var mysql = require('mysql');
var serveStatic = require('serve-static');
var bodyParser = require('body-parser');
var source = __dirname + '/public/views/index.html';
app.use(serveStatic(__dirname, {'index': ['index.html']}));
app.route('/*')
.get(function(req, res) {
res.sendFile(source);
});
var data;
var connection = mysql.createConnection({
host : 'thehostdb',
user : 'username', // credentials correct, connection works
password : 'pw',
database : 'db',
port: '3306'
});
connection.query('SELECT * from poemTable', function(err, rows, fields) {
if (!err) {
data = JSON.stringify(rows);
setDataValue(data);
}
else {
console.log('Error while performing Query:', err);
}
});
function setDataValue(value) {
data = value;
console.log(data); //Where the data logs
}
app.listen(port, function () {
console.log('Example app listening on port' + port + '!')
})
You have to understand what this code does, and how nodejs and angular are supposed to work together. Angular is served to the client and then rendered by the clients browser. So if you want to inject data you have to fetch it. So in your angular app when the controller starts make an api call, and in your server create a new route:
app.get('/data', function(req, res, next) {
connection.query(..., function(err, rows, fields) {
res.json(rows);
});
});
Make sure you understand node and it's async nature, what is event loop and how it works and what is callback hell, also I would check out promises and other tutorials on nodeschool.io, it's a great place to start with node :)

How to retrieve response from server using angularjs?

I am sending filename to server and trying to get some sort of response to make sure api calls are working but its always returing 404 even though path is correct, I am not sure where i am making mistake , Any idea ?
angularjsFactory.js
getFile:function(file_name){
return $http.get("/file?file_name="+file_name);
}
server.js
var express = require('express');
var app = express();
var fs = require('fs');
app.use(express.static(__dirname + "/public"));
var readDirectory = require('./readDirectory');
app.get('/file', function(req, res) {
var path = './ditLogs';
var fileParam = req.query.file_name;
console.log(fileParam);
fs.readdir(path, function(err, items) {
items.forEach(function(items) {
if (fileParam === items) {
res.sendFile(items);
console.log(items);
}
});
});
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
//console.log('app is printing data',obj);
//ditProducer.startProducer();
setTimeout(function() {
ditconsumer.start();
}, 2000);
});
Your route on server is not correct comparing to the call from angular's side. You are not using route parameters, but query string.
Try this:
app.get('/file', function (req, res) {
// get filename using: req.query.file_name
res.send('FIle data');
});
Or you can try this on angular and keep the server code:
$http.get("/file/"+ encodeURI(file_name));
Server side code looks incorrect.
app.get('/file', function (req, res) {
console.log(req.query.file_name);//This will give you filename passed as url param
res.send('FIle data');
});

posting scope variable through $http.post in angularjs

$http.post('/#/college', $scope.userb)
.success(function(data, status) {
console.log("Sent ok");
})
.error(function(data, status) {
console.log("Error");
})
[1]: http://i.stack.imgur.com/NlHyy.jpg
Is this the correct format/way to post my form data using http.post.?
The above code always returns "error" in the console.
please guide me to use http.post to post my form datathrough my controller.
var nodemailer = require("nodemailer");
var bodyparser = require("body-parser");
var app = express();
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
auth: {
user: "abc#gmail.com",
pass: "abc202"
}
});
var rand, mailOptions, host, link;
app.get('/#/college',function(req,res){
rand=Math.floor((Math.random() * 100) + 54);
host=req.get('host');
link="http://"+req.get('host')+"/verify?id="+rand;
mailOptions={
to : req.userb.counselloremail,
subject : "Please confirm your Email account",
html : "Hello,<br> Please Click on the link to verify your email.<br>Click here to verify"
}
console.log(mailOptions);
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
res.end("error");
}else{
console.log("Message sent: " + response.message);
res.end("sent");
}
});
app.use(morgan('dev'));
app.use(gzippo.staticGzip("" + __dirname + "/dist"));
app.listen(process.env.PORT || 5000);
I am trying to access the email address from the scope variable and post it so that i may send a confirmation mail that he is successfully registered now. Also I am sending the code of my web.js file that receives the posted data and sends the mail.
That URL you are posting to is not going to be valid.
If you are posting to another route in your app, the URL would just be #/college.
I'm also a little worried that you don't have anything setup to receive a post request, like on a server or anything. Could you give some more detail about what you are trying to do and your setup?
var dataObject = {
userid : LoginUserID
};
var responsePromise = $http.post(ApiAccessUrl+"/store/userstoreslist/", dataObject, {});
responsePromise.success(function(dataFromServer, status, headers, config)
{
var outputDate=angular.fromJson(dataFromServer);
});
responsePromise.error(function(data, status, headers, config) {
console.log("Error in fetching user store call!");
});
This is the correct way of sending data using http.post

Resources