Bluemix - Cloudant node.js: Error when calling API - javascript

I have a node.js app to call an API. The API works well on the first call, but on the second call, it returns this error message:
404 Not Found: Requested route ('abc.mybluemix.net') does not exist.
Please help review the app.js function:
app.js
app.get('/abc/:provider_id/staffs', function(request, response) {
console.log("Get method invoked.. ")
db = cloudant.use(dbCredentials.dbStaff);
//db = cloudant.use("staffs");
var docList = [];
db.list(function(err, body) {
if (!err) {
var len = body.rows.length;
console.log('total # of docs -> '+len);
if(len == 0) {
// error
} else {
var i = 0;
body.rows.forEach(function(document) {
db.search('allstaff', 'allstaff_index', {q:"provider_id:"+request.params.provider_id}, function(err, doc) {
if (!err) {
if(doc['_attachments']) {
// todo
} else {
var responseDataStaff = createResponseDataStaffs(
doc.rows[i].fields.id,
doc.rows[i].fields.provider_id,
doc.rows[i].fields.firstname,
doc.rows[i].fields.lastname,
doc.rows[i].fields.avatar,
doc.rows[i].fields.email,
doc.rows[i].fields.mobile,
doc.rows[i].fields.address,
doc.rows[i].fields.username,
doc.rows[i].fields.lastlogin,
doc.rows[i].fields.lastlogout
);
}
docList.push(responseDataStaff);
i++;
if(i >= doc.rows.length ) {
response.write(JSON.stringify(docList));
console.log('ending response...');
response.end();
}
} else {
console.log(err);
}
});
});
}
} else {
console.log(err);
}
});
and log file:

The reason you get 404 on the second time is because your app crashed.
Debug it locally before you push to Bluemix.
To debug locally you need to have VCAP_SERVICES defined for your app:
Open a terminal and type cf env
Copy the content of VCAP_SERVICES to a local file (e.g. VCAP_SERVICES.json)
Create a new file next to app.js (e.g. debugApp.js) with this content
if(!process.env.VCAP_SERVICES){
process.env.VCAP_SERVICES = JSON.stringify(require("./VCAP_Services.json"));
}
require('./app.js');
Then run node debugApp.js

I'm not sure what you're trying to achieve here but it looks bad
You're calling db.list to get a list of all your documents - fair enough
You then iterate through each document in the list to give a variable 'document' which you never use
You then issue a search request to Cloudant for each document you retrieved in the list. These search requests will be executed in parallel because they are started in a for loop. All of the search requests are identical and do not contain anything about the document you fetched.
I'm guessing that this isn't what you intended to do.

Related

Node-oracledb in browser error "Module name has not been loaded for context yet"

I'm trying to load data from oracle database using node-oracledb and im getting this error :
Error: Module name "select1" has not been loaded yet for context: _. Use require([])
I did read the documentation here, but i couldnt figure out a solution .Why is it giving me such error and why thanks for the help.
select1.js :
const oracledb = require('oracledb');
const dbConfig = require('./dbconfig.js');
const demoSetup = require('./demosetup.js');
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT;
async function run() {
let connection;
try {
// Get a non-pooled connection
connection = await oracledb.getConnection(dbConfig);
await demoSetup.setupBf(connection); // create the demo table
var query = await connection.execute(
// The statement to execute
`SELECT * From pilote`,
// The "bind value" 3 for the bind variable ":idbv"
[],
// Options argument. Since the query only returns one
// row, we can optimize memory usage by reducing the default
// maxRows value. For the complete list of other options see
// the documentation.
{
maxRows: 100
//, outFormat: oracledb.OUT_FORMAT_OBJECT // query result format
//, extendedMetaData: true // get extra metadata
//, fetchArraySize: 100 // internal buffer allocation size for tuning
});
//console.log(query.rows)
} catch (err) {
console.error(err);
} finally {
if (connection) {
try {
// Connections should always be released when not needed
//await connection.close();
} catch (err) {
console.error(err);
}
}
}
return query;
}
module.exports.run = run;
test.js :
(async() =>{
var result = require('./select1').run()
var rs;
rs = (await result).rows
if(rs !== undefined)
{
document.getElementById('hdr').textContent = rs[0]
}
})()
page.html :
<body>
<h1 id="hdr">hello</h1>
<script src="https://requirejs.org/docs/release/2.3.5/minified/require.js"></script>
<script src="test.js"></script>
</body>
node-oracledb will not run in a browser because has a binary component that needs access to binary shared libraries. A standard Node.js application design has Node.js as a mid-tier application server that accepts networks calls e.g. REST, from the broswer and returns data to that browser. There are a few usage variants, e.g. as a standalone app using Electron.
If it's all new to you, start with the example https://github.com/oracle/node-oracledb/blob/master/examples/webappawait.js and work up to https://jsao.io/2018/03/creating-a-rest-api-with-node-js-and-oracle-database/

In Node, how to execute sql from global database connection

I am unable to execute the sql, when using the global database connection in node.js.
I have followed the steps as in Azure documentation: https://learn.microsoft.com/en-us/azure/mysql/connect-nodejs and able to display the output on the console. But, I want to put all my Azure SQL database connection in a separate file, but the select query is not printing the output on the console.
DatabaseManager.js
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var sqlConnection = function sqlConnection() {
// Create connection to database
var config =
{
userName: 'uname',
password: 'password',
server: 'dbserver.database.windows.net',
options:
{
database: 'mydatabase',
encrypt: true
}
}
var connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on('connect', function(err) {
if (err)
{
console.log(err)
}
else
{
console.log('CONNECTED TO DATABASE');
}
}
);
}
module.exports = sqlConnection;
app.js
var restify = require('restify');
var builder = require('botbuilder');
var botbuilder_azure = require("botbuilder-azure");
var azure = require('azure-storage');
var dbconnection = require('./DatabaseManager');
bot.dialog('profileDialog',
(session) => {
session.send('You reached the profile intent. You said \'%s\'.', session.message.text);
console.log('Reading rows from the Table...');
dbconnection("select FNAME from StudentProfile where ID=1"),
function (err, result, fields) {
if (err) throw err;
console.log(result);
}
session.endDialog();
}
Console Output:
Reading rows from the Table...
CONNECTED TO DATABASE
I was expecting the output of FNAME, but nothing is printing on the console. Is there anything, I am missing?
Thank you.
There's a couple of problems here. First off, you should only ever import a module once per file. This is just a performance consideration and won't actually break your code.
Next, pay attention to what you're exporting from your DatabaseManager module. Right now, you're exporting a function that creates the connection and then doesn't do anything with it. We can fix this by using a pattern called a "callback" which lets us provide a function that will then be called with the connection as an argument.
I added a ton of comments to the code explaining things. This code won't run as-is - there's a couple places where I have "do this or this". You'll have to choose one.
var Tedious = require('tedious'); // Only require a library once per file
var Connection = Tedious.Connection;
var Request = Tedious.Request;
// Or using the object spread operator
var { Connection, Request } = require('tedious');
// You called this `sqlConnection`. I'm going to use a verb since it's a
// function and not a variable containing the connection. I'm also going
// to change the declaration syntax to be clearer.
function connect(cb) { // cb is short for callback. It should be a function.
var config = {
userName: 'uname',
password: 'password',
server: 'dbserver.database.windows.net',
options: {
database: 'mydatabase',
encrypt: true
}
}; // Put a semi-colon on your variable assignments
var connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on('connect', function(err) {
if (err) {
console.log(err);
return; // Stop executing the function if it failed
}
// We don't need an "else" because of the return statement above
console.log('CONNECTED TO DATABASE');
// We have a connection, now let's do something with it. Call the
// callback and pass it the connection.
cb(connection);
});
}
module.exports = connect; // This exports a function that creates the connection
Then back in your main file, you can use it like so.
var restify = require('restify');
var builder = require('botbuilder');
var botbuilder_azure = require('botbuilder-azure');
var azure = require('azure-storage');
var connect = require('./DatabaseManager'); // renamed to be a verb since it's a function.
bot.dialog('profileDialog', (session) => { // Hey, this is a callback too!
session.send('You reached the profile intent. You said \'%s\'.', session.message.text);
console.log('Creating a connection');
connect((connection) => {
// or with the traditional function notation
connect(function(connection) {
console.log('Reading rows from the Table...');
// Execute your queries here using your connection. This code is
// taken from
// https://github.com/tediousjs/tedious/blob/master/examples/minimal.js
request = new Request("select FNAME from StudentProfile where ID=1", function(err, rowCount) { // Look another callback!
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
connection.close();
});
request.on('row', function(columns) { // Iterate through the rows using a callback
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log(column.value);
}
});
});
connection.execSql(request);
});

Nodejs unable to kill external windows executable program executed by Node itself

I am hosting Node as a server locally to interact with hardware.
My web application then makes a request to Node to execute 2 executable, whichever executable returns a data first will Respond it back to my Web Application.
By doing so, it causes the other executable to still be running in the background waiting for response from the hardware.
I am unable to kill off that process either, I have to either manually stop Node and run it again or task kill that executable.
My code are below:
Node.JS
var exec = require('child_process').exec;
app.get('/Page', function (req, res) {
var Page = function () {
var a = exec('F:/Example1.exe', function (err, data) {
console.log(err);
console.log(data);
b.kill();
if (!res.headersSent) {
res.send(data);
}
});
var b = exec('F:/Example2.exe', function (err, data) {
console.log(err);
console.log(data);
a.kill();
if (!res.headersSent) {
res.send(data);
}
});
}
Page();
});
Apparently, even with the kill command, I am still unable to terminate the process.
I should let you guys know, I am also using AngularJS for my front-end.
I have sourced online for solution, however Google's results are all slowly turning purple.
Thank you so much for those who post their solution, please explain to me the details of the solution as well. I would really want to learn more.
Thank you so much.
The problem with exec is it will wait until the program has executed for it's callback to run.
You can use spawn instead, then you have control over the process as it's running.
var spawn = require('child_process').spawn;
app.get('/Page', function(req, res) {
var Page = function() {
var a = spawn('F:/Example1.exe');
var b = spawn('F:/Example2.exe');
var aData = '',
bData = '';
a.stdout.on('data', function(data) {
aData += data.toString();
});
b.stdout.on('data', function(data) {
bData += data.toString();
});
a.on('close', function() {
b.kill();
if (!res.headersSent) {
res.send(aData);
}
});
b.on('close', function() {
a.kill();
if (!res.headersSent) {
res.send(bData);
}
});
}
Page();
});
I have never used exec in nodejs but javascript scoping I think Page is executed every request, so the a and b processes from previous requests are no longer around.
You could store references to the processes globally so that each request has access to the processes, (real incomplete rough example):
var exec = require('child_process').exec;
var a = null;
var b = null;
app.get('/Page', function (req, res) {
var Page = function () {
if (a) {
// a is already a running process? Do something?
} else {
// start a ?
a = exec('your command');
}
if (b) {
// b is already running? Do something?
}
}
Page();
});

Node.js script stops without any error

I've written a scraper using the scraper module and the queue function of async module.
I read the list of URLs to scrap from a json file and write the informations in another JSON file.
This is my script:
var fs = require("fs");
var scrap = require("scrap"),
async = require("async");
var errors = [];
// Queue a list of URLs
var queue = JSON.parse(fs.readFileSync("products.json", "utf8"));
var len = queue.products.length;
var q = async.queue(function (url, done) {
scrap(url, function(err, $) {
var product = {};
product.name = $("#page-body h2").first().text().trim();
product.myarr = [];
product.picture = $(".content img").first().attr("src");
try {
if (product.picture.indexOf("someword") > 1) {
delete product.picture;
}
}
catch (e) {
console.error(e);
}
$(".content [style^=\"color: #\"] [style=\"font-weight: bold\"], .content [style=\"font-weight: bold\"] [style^=\"color: #\"]").each(function() {
product.myarr.push($(this).text().trim().toLowerCase());
});
if (product.myarr.length) {
fs.appendFile("products-parsed.json", JSON.stringify(product) + ",\n", function (err) {
console.log(queue.products.indexOf(url), len, err);
if (err) { errors.push(queue.products.indexOf(url)); }
done();
});
}
});
}, 20);
q.drain = function() {
console.log(errors);
};
q.push(queue.products);
When I run it, after about 3.000 pages, it stops (quit) and it does not give any error, I have to start from the latest worked page using:
q.push(queue.products.slice(lastWorkedPage, queue.products.length - 1));
How can I fix this problem?
Not sure why, by the way seems like the problem was caused by this row:
console.log(queue.products.indexOf(url), len, err);
Commenting it has solved the problem, feel free to give a more accurate answer which explains the solution and I'll set it as accepted.
Can't comment yet so I have to post new answer.
I can confirm console.log - error. NodeJS/Express sometimes just stops when trying to use console.log()!
Code from one test-project:
console.log(req.body.credentials.password, isMatch);
if (isMatch) {
sess.currentUser = user;
console.log(user);
res.send({ status: "ok", loginUser: user });
}
else {
res.send({ status : "error", msg: "Login failed!" });
}
Second logging line (console.log(user)) stops NodeJS without error! And that happens only in some environments - in most dev environments this works just fine!

How do I run an asynchronous 'find' in a loop while incrementing the find parameter so I can generate unique custom id's?

I'm new to mongoose/mongodb and I am trying to do some sort of error handling with my document save.
I am trying to create a stub id to store into the db for easier data retrieval later on (and also to put into the url bar so people can send links to my website to that particular page more easily -- like jsfiddle or codepen).
Basically I want to search for a document with a page_id and if it exists, I want to regenerate that page_id and search until it gets to one that's unused like this:
while(!done){
Model.findOne({'page_id': some_hex}, function (err, doc) {
if(doc){
some_hex = generate_hex();
}
else
{
done = true;
}
});
}
model.page_id = some_hex;
model.save();
However, since mongoose is asynchronous, the while loop will pretty much run indefinitely while the find works in the background until it finds something. This will kill the resources on the server.
I'm looking for an efficient way to retry save() when it fails (with a change to page_id). Or to try and find an unused page_id. I have page_id marked as unique:true in my schema.
Retrying should be performed asynchronously:
var tryToSave = function(doc, callback) {
var instance = new Model(doc);
instance.page_id = generate_hex();
instance.save(function(err) {
if (err)
if (err.code === 11000) { // 'duplicate key error'
// retry
return tryToSave(doc, callback);
} else {
// another error
return callback(err);
}
}
// it worked!
callback(null, instance);
});
};
// And somewhere else:
tryToSave(doc, function(err, instance) {
if (err) ...; // handle errors
...
});

Categories

Resources