How to use node sqlite3 with q (promise) - javascript

I'm trying to use the promise with sqlite3. Here is a part of my source code:
this.deleteTag = function(tag, project){
var db = this.db;
if (project){
return q.nfcall(db.run, "DELETE FROM tag2project WHERE tag = ? AND project = ?",
[tag.id, project.id]);
}else{
return q.all([
q.nfcall(db.run, "DELETE FROM tag2project WHERE tag = ?", [tag.id]),
q.nfcall(db.run, "DELETE FROM tags WHERE id = ?", [tag.id])
]);
}
};
But those promises only enter in .fail where error is:
[TypeError: Database object expected]
Searching for this error only got me to the sourcecode of sqlite itself https://github.com/joyent/smartos-live/blob/master/src/node-sqlite3/src/statement.cc#L91
The old version using simple callback is working so there is not error in this.db or the sql query.

I think db.run is not function but method. from Q doc:
If you are working with methods, instead of simple functions, you can
easily run in to the usual problems where passing a method to another
function—like Q.nfcall—"un-binds" the method from its owner. To avoid
this, you can either use Function.prototype.bind or some nice
shortcut methods we provide:
return Q.ninvoke(redisClient, "get", "user:1:id");
return Q.npost(redisClient, "get", ["user:1:id"]);
But I always use Q.denodeify or Q.nbind. it is cleaner.
You can also create reusable wrappers with Q.denodeify or Q.nbind:
var readFile = Q.denodeify(FS.readFile);
return readFile("foo.txt", "utf-8");
var redisClientGet = Q.nbind(redisClient.get, redisClient);
return redisClientGet("user:1:id");

You could bind the object that you created when you promisify the function.
Example
const { promisify } = require('util');
const db = new lib_sqlite3.Database(_dirname + '/your-db-path');
const runAsync = promisify(db.run.bind(db));

Related

How to retrieve the text using protractor's getText API?

I am using protractor for my test framework and I need to get the value by using the getText method and store it in another value. I have problem in extracting the value from getText method. I do understand that I need to resolve the promise but it didn't work for me.
I have the page object like this. (Emp.js)
this.getID = async()=>{
await empID.getText();
}
and in the test.spec.js. This is how I have my test to retrieve the file.
var emp = new emp();
let empID = await emp.getID();
//When I do console.log(empID) it returns undefined. not sure why ?
Please try this:
this.getID = async() => {
return await empID.getText();
}

NodeJS mysql2 Bluebird?

Been testing mysql vs mysql2, seems like 2 has made some improvments however it's not an exact drop in replacement. At the same time Q is a good library which seems easier to integrate with however bluebird seems to take less memory and run faster so...
My current mysql-bluebird connector is as follows and allows for straight forward use of query('SELECT email FROM users.users WHERE id=?',id).then(function(res){var email=res[0][0];});
/* global module, require */
var conf=require('./conf.js').conf;
var mysql = require('mysql');
var Promise = require('bluebird');
var using = Promise.using;
Promise.promisifyAll(require('mysql/lib/Connection').prototype);
Promise.promisifyAll(require('mysql/lib/Pool').prototype);
var pool = mysql.createPool(conf.mysql);
var getConnection = function () {
return pool.getConnectionAsync().disposer(function (connection) {
return connection.release();
});
};
var query = function (command) {
return using(getConnection(), function (connection) {
return connection.queryAsync(command);
});
};
function queryWrapper(q,a){
if(a){
return query(mysql.format(q,a));
}
else{
return query(mysql.format(q));
}
}
module.exports = {
query: queryWrapper
};
So far my attempts ad doing this with mysql2 haven't panned out.
Does anyone have any insights on how to convert this?
Thanks, Jegsar
You can use mysql2-promise. It's a simple wrapper, using q, that promisifies mysql2. If you'd rather use Bluebird, you can look at how this wrapper was created and do it yourself.
node-mysql2 now has Promise api built in, and you can choose which promise implementation you want to use
var mysql = require('mysql2/promise');
mysql.createConnection({
Promise: require('bluebird'), // if not set, global Promise is used
user: 'foo',
password: 'bar',
database: 'baz'
})
.then((conn) => conn.query('select 1+1 as test'))
.then(([rows, fields]) => console.log(rows[0]))

Unable to get bluebird promise and mongoose's save() to work in node.js

Can anyone help me figure out how to rewrite the following working code in promise? I want to execute an insert query and then send the data back to clients via socket.js
var func = require("functions")
var mongoose = require('mongoose');
var mongo_models = require('./database/mongo_model')(mongoose);
var Promise = require("bluebird");
socket.on("submit",function(d){
if(d[0].src !== undefined)
{
var data = func.clear(sanitizer,d),
tab = new mongo_models.Tab({avg:0,post:data});
tab.save(function(err,tw){
io.sockets.in('index').emit("update",tw)
})
}
});
I have tried the following code but I'm getting undefined from console.log(b). Apparently the save() isn't returning any result.
Promise:
socket.on("submit",function(d){
if(d[0].src !== undefined)
{
Promise.props({
one: func.clear(sanitizer,d)
}).then(function(a){
return new mongo_models.Tab({avg:0,post:a.one}).save();
}).then(function(b){
console.log(b); // undefined
io.sockets.in('index').emit("update",b)
}).catch(function (error) {
console.log(error);
})
}
});
Save is problematic in Mongoose as being an exception to the rule of promise returning functions there.
I highly recommend that you promisify mongoose using bluebird which exposes a saveAsync function:
var Promise = require("bluebird");
var func = require("functions")
var mongoose = Promise.promisifyAll(require('mongoose'));
var mongo_models = require('./database/mongo_model')(mongoose);
And then return the async call as:
// Note the suffix
return new mongo_models.Tab({avg:0,post:a.one}).saveAsync();

Nodejs delay return for "require"

My setup is as follows:
Nodejs Server
server.js requires utils.js
utils.js loads data from mongodb into memory and exports it
server.js uses a variable that utils.js exports
The issue that I am worried about is the fact that the mongodb call is asynchronous. utils.js returns before the mongodb call is finished, meaning that server.js will use an undefined variable when it continues execution after the require.
What is the best to address this issue? The only thing I could think of is wrapping my server.js code in a giant callback and pass that to the function that makes the mongodb call. It seems a bit messy to me, is there a better way to do it?
Code:
server.js
var utils = require("./modules/utils.js");
console.log(utils);
//Do whatever
utils.js
var mods = [];
var db = require("mongojs").connect("localhost", ["modules"]);
db.modules.find({}, function(err, modules){
mods = modules;
});
module.exports = mods;
What you're referring to is called "callback hell". The easiest way to get out of that is to use a Promise library that simplifies it.
I used a node package called bluebird.
var mysql = require("mysql");
var hash = require("password-hash");
var Promise = require("bluebird");
var settings = require("../settings");
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
var db_config = {
user:settings.db.user,
password:settings.db.password,
database:settings.db.database
};
var con = mysql.createPool(db_config);
function query(sql) {
return con.getConnectionAsync().then(function(connection) {
return connection.queryAsync(sql)
.spread(function(rows,fields) {
return rows;
}).finally(function() {
connection.release();
});
});
}
This is a very basic database module I wrote that uses bluebird to promisify the database object.
And here's how it's used. It returns a promise! The benefit here is that not only does it return the clutter of callback hell, it makes sure that your code runs asynchronously and the function does not return before things have stopped processing, like in this case, a database query.
function login(user) {
//check for player existance
var query = 'SELECT p.name,p.password,p.id, pd.x, pd.y FROM player p INNER JOIN player_data pd ON p.id = pd.id WHERE p.name='+mysql.escape(user);
return db.select(query).then(function(rows) {
if (!rows.length) return;
return [
rows[0]
];
});
}
Notice how you return a promise, so that you call the then or spread method to get those database values you just queried, not having to worry about if rows will be undefined by the time you want to use it.
As you say, you need to wrap the entire server in a callback. Node.js works this way, it's asynchronous by nature. A server needs to pass through 3 stages: init, serve and deinit. In your case, that database code goes inside the init stage. You could write something like this.
//server.js
var utils = require ("./modules/utils");
var init = function (cb){
//init the utils module, the http server and whatever you need
utils.init (function (error){
if (error) return handleError (error);
cb ();
});
};
var serve = function (){
//Start listening to the http requests
};
var deinit = function (cb){
//This is typically executed when a SIGINT is received, see link1
};
init (serve);
//utils.js
//You could write a wrapper for the db instance, see link2
var mongodb = require ("mongojs");
var db;
module.exports.init = function (cb){
db = mongodb.connect ("localhost", ["modules"]);
db.modules.find ({}, function (err, modules){
if (err) return cb (err);
cb (null, modules);
});
};
I don't recommend using promises, they are slower than raw callbacks. You don't need them at all.
link1 - SIGINT
link2 - db wrapper

Get DNS MX records in Node

I want to get MX records for hostname www.example.com. Node has got function for it.
dns.resolveMx(domain, callback)
But i don't want that callback thingy. I want something like sync call. e.g.
var records = dns.resolveMx(domain);
Is this possible ?
(Note:- I found that function in Node documentation. link:- http://nodejs.org/api/dns.html)
Update 2021
There is now a promises submodule under dns module if some one is looking for sync calls.
Check more here
https://nodejs.org/api/dns.html#dns_class_dnspromises_resolver
const dnsPromises = require('dns').promises;
const demo1 = await dnsPromises.resolveMx("gmail.com");
Is there any reason you want to block your application with a network operation? The DNS resolvers are called at the C level by the c-ares library which is asynchronous by design. Therefore, you can't make it synchronous. This is the code from the DNS module with the unneeded parts removed:
var cares = process.binding('cares_wrap');
function resolver(bindingName) {
var binding = cares[bindingName];
return function query(name, callback) {
callback = makeAsync(callback);
var req = {
bindingName: bindingName,
callback: callback,
oncomplete: onresolve
};
var err = binding(req, name);
if (err) throw errnoException(err, bindingName);
callback.immediately = true;
return req;
}
}
var resolveMap = {};
exports.resolveMx = resolveMap.MX = resolver('queryMx');

Categories

Resources