Node.js does not wait for the MySQL server sends the answer, and continues to work asynchronously - mysql

Print haphazardly and not wait for MySQL send a reply.
var mysql=require('mysql').createConnection({
host:'localhost',user:'root',password:'',database:'dbname',port:3306
});
mysql.connect(function(error){if(error){throw error;}else{console.log('MYSQL SERVER [OK]');}});
console.log('// INI //');
var sql='SELECT * FROM sys_users';
mysql.query(sql,function(error,rows){
if(!error){
for(i=0;i<rows.length;i++){
if(i<rows.length-1)
console.log(rows[i].username);
else console.log(rows[i].username);
}
}else console.log('Error');
});
console.log('// END //');
mysql.end();
would have to print:
MYSQL SERVER [OK]
// INI //
List item
// END //
but nevertheless printed:
// INI //
// END //
MYSQL SERVER [OK]
List item

That's the nature of Node.js - callbacks and async code processing.
If you want to run come code after the database response will be returned, place that code inside the callback:
mysql.query(sql,function(error,rows){
if (!error){
for(i=0;i<rows.length;i++){
if(i<rows.length-1)
console.log(rows[i].username);
else
console.log(rows[i].username);
}
} else {
console.log('Error');
}
/* Code to run. Move it to first `if`, if you want to run it only, when no error will occur. */
console.log('//END //');
});
mysql.end();

Related

How to load data from api if json changes? Watcher on json? Visualizing data with vue-chartjs and axios

I have built charts with vue-chartjs and fetch data from an api with axios. Currently i have a setInterval to load the JSON every 10 seconds. I want to avoid that and load data only if the json changes. How to do that? I tried to set a watcher on this.chart1Data, but did not work.
Here is the codesandbox: https://codesandbox.io/s/vue-chartjs-json-data-rnv2v?file=/src/App.vue
I think what you're looking for are WebSockets:
var socket = new WebSocket(urlToWebsocketServer);
// callback method is called when connection is established
socket.onopen = function () {
console.log("Connection established");
};
// callback method is called when a new websocket messages is received
socket.onmessage = function (messageEvent) {
console.log(messageEvent.data);
};
// callback method is called when there was an error
socket.onerror = function (errorEvent) {
console.log("Error! Connection was closed");
};
socket.onclose = function (closeEvent) {
console.log('Connection closed --- code: ' + closeEvent.code + ' --- reason: ' + closeEvent.reason);
};
I borrowed this code from wikipedia ;)
Edit: There are many tutorials out there. Just use Google. Maybe this one could be helpful

PWA: Chrome warning "Service worker does not have the 'fetch' handler"

I'm currently unsuccessfully trying to make my PWA installable. I have registered a SertviceWorker and linked a manifest as well as I am listening on the beforeInstallPromt event.
My ServiceWorker is listening to any fetch event.
My problem is, that the created beforeInstall banner is just being shown on Chrome desktop but on mobile I get a warning in Chrome inspection tab "Application" in the "Manifest" section:
Installability
Service worker does not have the 'fetch' handler
You can check the message on https://dev.testapp.ga/
window.addEventListener('beforeinstallprompt', (e) => {
// Stash the event so it can be triggered later.
deferredPrompt = e;
mtShowInstallButton();
});
manifest.json
{"name":"TestApp","short_name":"TestApp","start_url":"https://testapp.ga/loginCheck","icons":[{"src":"https://testapp.ga/assets/icons/launcher-ldpi.png","sizes":"36x36","density":0.75},{"src":"https://testapp.ga/assets/icons/launcher-mdpi.png","sizes":"48x48","density":1},{"src":"https://testapp.ga/assets/icons/launcher-hdpi.png","sizes":"72x72","density":1.5},{"src":"https://testapp.ga/assets/icons/launcher-xhdpi.png","sizes":"96x96","density":2},{"src":"https://testapp.ga/assets/icons/launcher-xxhdpi.png","sizes":"144x144","density":3},{"src":"https://testapp.ga/assets/icons/launcher-xxxhdpi.png","sizes":"192x192","density":4},{"src":"https://testapp.ga/assets/icons/launcher-web.png","sizes":"512x512","density":10}],"display":"standalone","background_color":"#ffffff","theme_color":"#0288d1","orientation":"any"}
ServiceWorker:
//This array should NEVER contain any file which doesn't exist. Otherwise no single file can be cached.
var preCache=[
'/favicon.png',
'/favicon.ico',
'/assets/Bears/bear-standard.png',
'/assets/jsInclude/mathjax.js',
'/material.js',
'/main.js',
'functions.js',
'/material.css',
'/materialcolors.css',
'/user.css',
'/translations.json',
'/roboto.css',
'/sw.js',
'/'
];
//Please specify the version off your App. For every new version, any files are being refreched.
var appVersion="v0.2.1";
//Please specify all files which sould never be cached
var noCache=[
'/api/'
];
//On installation of app, all files from preCache are being stored automatically.
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(appVersion+'-offline').then(function(cache) {
return cache.addAll(preCache).then(function(){
console.log('mtSW: Given files were successfully pre-cached')
});
})
);
});
function shouldCache(url) {
//Checking if url is market as noCache
var isNoCache=noCache.includes(url.substr(8).substr(url.substr(8).indexOf("/")))||noCache.includes((url.substr(8).substr(url.substr(8).indexOf("/"))).substr(0,(url.substr(8).substr(url.substr(8).indexOf("/"))).indexOf("?")));
//Checking of hostname of request != current hostname
var isOtherHost=url.substr(8).substr(0,url.substr(8).indexOf("/"))!=location.hostname&&url.substr(7).substr(0,url.substr(7).indexOf("/"))!=location.hostname;
return((url.substr(0,4)=="http"||url.substr(0,3)=="ftp") && isNoCache==false && isOtherHost==false);
}
//If any fetch fails, it will look for the request in the cache and serve it from there first
self.addEventListener('fetch', function(event) {
//Trying to answer with "online" version if fails, using cache.
event.respondWith(
fetch(event.request).then(function (response) {
if(shouldCache(response.url)) {
console.log('mtSW: Adding file to cache: '+response.url);
caches.open(appVersion+'-offline').then(function(cache) {
cache.add(new Request(response.url));
});
}
return(response);
}).catch(function(error) {
console.log( 'mtSW: Error fetching. Serving content from cache: ' + error );
//Check to see if you have it in the cache
//Return response
//If not in the cache, then return error page
return caches.open(appVersion+'-offline').then(function (cache) {
return cache.match(event.request).then(function (matching) {
var report = !matching || matching.status == 404?Promise.reject('no-match'): matching;
return report
});
});
})
);
})
I checked the mtShowInstallButton function. It's fully working on desktop.
What does this mean? On the Desktop, I never got this warning, just when using a handheld device/emulator.
Fetch function is used to fetch JSon manifest file. Try reading google docs again.
For adding PWA in Mobile you need manifest file to be fetched which is fetched using service-worker using fetch function.
Here is the code :
fetch('examples/example.json')
.then(function(response) {
// Do stuff with the response
})
.catch(function(error) {
console.log('Looks like there was a problem: \n', error);
});
for more about fetch and manifest try this.

Unable to return JSON response to client using Node

I am having trouble returning a JSON object back to a client upon request - I am just working with the first GET call to '/btc'.
//Main server to recieve requests
http.createServer(function(req,res){
switch(req.method){
case 'GET':
switch(req.url){
case '/btc':
callBtcApi(req,res)
console.log(' btc called');
break;
case '/wallet':
callBtcWallet(req,res)
console.log('wallet called');
break;
case '/weather':
callWeather(req,res);
console.log('weather called');
break
default:
console.log('calling but not hitting');
break;
}
case 'POST':
switch(req.url){
case '/update':
console.log('update called');
break;
}
}
}).listen(3000);
callBtcApi() below, queries a bitcoin API and returns a JSON object successfully (I do intend to do more with the function, just getting the basics down first). callBtcApi() is successfully being called.
function callBtcApi(req,res){
message = '';
https.get('https://api.bitcoinaverage.com/ticker/global/GBP/', function(res){
res.on('data',function(data){
message += data;
});
res.on('end',function(){
console.log('props called ;)');
writeToCLient(res,message);
});
}).on('error', function(e){
console.error(e);
});
}
The issue I am having is when I then pass this data to my writeToCLient() function in res.on('end'). The error i receive in the terminal is
TypeError: res.setHeader is not a function
I know the message is passed into the function writeToCLient() as I am able to see the data in the terminal when I console.log(message) if I temporarurly hide all of the res.() calls.
function writeToCLient(res,message){
console.log(message);
res.statusCode = 200;
res.setHeader('Content-Type','application/json');
res.end(JSON.stringify(message));
}
I have searched google but haven't found anything that explains what could be the issue. Is the issue possibly down to calling a HTTP.get() request from inside callBtcApi() which is sitting inside my main server?
Thanks
Can you try with this?
function callBtcApi(request,response){
message = '';
https.get('https://api.bitcoinaverage.com/ticker/global/GBP/', function(res){
res.on('data',function(data){
message += data;
});
res.on('end',function(){
console.log('props called ;)');
writeToCLient(response,message);
});
}).on('error', function(e){
console.error(e);
});
}

Possible to have node.js redis fallback?

In Laravel, you can do something like
$object = Cache->remember(key, duration, function() {
$result = mysql_fetch_something();// retrieve from MySQL here
return $result;
});
where basically, Laravel checks the cache first if it exists there, and if not, it allows you to retrieve the value from the database and automatically put it in cache while also returning it. Is there a similar construct in node; that is, a 1 stop cache check, db failover mechanism?
In node there is no special command for this but you can build it yourself.
Just check with the redis command EXISTS whether the key is in redis and if not just check mysql and store it.
You can do some thing like this. in cache.js
var isCacheAvailable = true;
exports.init = function () {
var server = config.get('Cache.server');
var port = config.get('Cache.port');
client = redis.createClient(port,server);
// handle redis connection temporarily going down without app crashing
client.on("error", function (err) {
logger.error("Error connecting to redis server " + server + ":" + port, err);
isCacheAvailable = false;
});
}
exports.isCacheAvailable = function(){
return isCacheAvailable;
}
Check the isCacheAvailable() function where you intend to use cache.
if(cache.isCacheAvailable()) {
// use cache to fetch data
} else {
// fallback to mysql db
}
Hope this helps.

node.js / node_mysql - stale connections get "NO database selected" error

We have a node.js app that uses node_msyql, a great little library for accessing MySQL databases.
Unfortunately, if our connection is not used for maybe 8-10 hours, the next time we try to run a query, we get a "No database selected" error back from the server. We need to add a "USE db" somewhere, but I can't figure out where.
Now, it makes sense to me that connections would go stale, and it seems as though node_mysql is refreshing those stale connections, but there doesn't seem to be a way to make sure that the right db is connected. I was looking for a .connected() callback or event or something that would let me make sure the correct DB was alway USE'd, but no luck so far.
Any suggestions how to do this?
Ys, client tries to reconnect. You can try to query 'use db' on reconnect using code like this:
client._connection.on('connect', function() { client.query('use db'); })
This is where reconnection happen in the node-mysql ('end' handler):
https://github.com/felixge/node-mysql/blob/master/lib/mysql/client.js
var connection = self._connection = new Stream(),
parser = self._parser = new Parser();
connection
.on('error', function(err) {
var connectionError = err.code && err.code.match(/ECONNREFUSED|ENOTFOUND/);
if (connectionError) {
if (cb) {
cb(err);
return;
}
}
self.emit('error', err);
})
.on('data', function(b) {
parser.write(b);
})
.on('end', function() {
if (self.ending) {
self.connected = false;
self.ending = false;
return;
}
if (!self.connected) {
return;
}
self.connected = false;
self._prequeue(connect);
});
connection.connect(self.port, self.host);
because of node-mysql update following code maybe work:
client._socket.on('connect', function() {
console.log("use ",DB_NAME);
client.query('use '+DB_NAME);
});
When using the node-mysql-promise package, you may want to use this code to do the same:
dbConn.pool.on('connection', function() {
dbConn.pool.query("USE myDBname");
} );