Can't call nodeify on async function but can call then() - node.js

I have these 2 functions.
async function testAsync(){
console.log('async func')
}
function callback(){
console.log('callback function.')
}
When I call then on async it works, similar to the promise. For example, the following code works.
bluebird.resolve().then(()=> console.log('then promise'))
testAsync().then(()=> console.log('then async'))
But when I call nodeify on async then it gives error. Although, it works for promise
Works ->bluebird.resolve().nodeify(callback)
Error -> testAsync().nodeify(callback)
This is the error that I got. Why so?
TypeError: testAsync(...).nodeify is not a function

The error states that there is no nodeify function on the native promise object.
If you need to use this function, which you really shouldn't, you have to get it from the promise implementation that defines it and call it on the object something like p.prototype.nodeify.call(testAsync()) and then hope that it does not use any internal parts of the promise implementation.
Or better extract the function from the promise implementation because it is only something like this:
function nodeify(cb) {
this.then(function (v) { cb(null, v) });
this.catch(function (err) { cb(err) });
}
which can be used as nodeify.call(testAsync(), callback)

Related

Error: Transaction rejected with non-error: undefined

I am using knex npm version 0.15.2. while Rollback the transaction I'm getting the following error:
Error: Transaction rejected with non-error: undefined
Trx.rollback()
above function used for rollback.
Same code working for knex version 0.12.6
This is the function I used for commit/Rollback.
function Commit(pTrx, pIsCommit, pCallback) {
try {
var co = require("co");
var q = require('q');
var Q = q.defer();
co(function* () {
if (pIsCommit) {
yield pTrx.commit();
} else {
yield pTrx.rollback();
}
Q.resolve(pCallback('SUCCESS'));
}).catch(function (error) {
Q.reject(pCallback(error));
});
return Q.promise;
} catch (error) {
console.log(error)
}
}
This code could use some work. :) Here are a few things that pop out:
You don't need co or q anymore. Promises and async/await are built-in and much simpler to use. Async functions automatically return promises that will be resolved with the value returned or rejected if an error is thrown. Learn about async/await here: https://jsao.io/2017/07/how-to-get-use-and-close-a-db-connection-using-async-functions/
You shouldn't return success as a string. If the function completes without throwing an exception, then success is implied. I see people do this from time to time, but it's often for the wrong reasons.
You shouldn't accept callback in a function that returns a promise, it should be one or the other. The caller of your function will either pass a callback or await it's completion.
If you are going to use callbacks, then you should return null as the first parameter when successful. See the last sentence here: https://nodejs.org/en/knowledge/getting-started/control-flow/what-are-callbacks/
Your function name, Commit, starts with an uppercase. This convention is typically used to indicate that the function is a contstructor function and meant to be invoked with the new keyword.
Here's how the function could look once cleaned up:
async function commit(pTrx, pIsCommit) {
// Not using a try/catch. If an error is thrown the promise returned will be rejected.
if (pIsCommit) {
await pTrx.commit();
} else {
await pTrx.rollback();
}
// Not going to return anything. If we get to this point then success is implied when the promise is resolved.
}
A consumer of your function would call it with something like:
async function myWork() {
// do work; get pTrx
try {
await commit(pTrx, true);
// If I get here, then I can assume commit was successful, no need to check a return value of 'SUCCESS'
} catch (err) {
// handle error
}
}
It's hard to say where the issue is with the code in its current state. However, if the issue truly is with Knex, then you should probably post this as an issue in the Knex repo: https://github.com/tgriesser/knex/issues But you should write a reproducible test case that proves its an issue with Knex.

Promise chain not executing in expected order - nodejs

I have a chain of 4 promises, and 1 function at the end. The final function is executing before the previous promises in the chain have resolved.
Can someone explain to me why this might be happening?
Here is the promise chain:
updateGdax(db)
.then(updateBitstamp(db))
.then(updateBitfinex(db))
.then(updatePoloniex(db))
.then(coinMarketData.updateCoinMarketData(db))
.then(addRates(db)); //this function is executing after the first promise in the chain.
I would like each function to execute after the one listed before it, so addRates(db) should be executed last.
I can post the code from the promise functions if needed for further analyses, but I really just want to understand WHY this would happen, as my understanding is that functions in a promise chain won't execute unless the previous promise in the chain has resolved.
Unless those update functions in the then calls are partially applied (unless they return a function), they are being executed before the then is called. You need to wrap them in an anonymous function to have them executed in order. Do what the other answer says or use fat arrows:
updateGdax(db)
.then(()=>updateBitstamp(db))
.then(()=>updateBitfinex(db))
.then(()=>updatePoloniex(db))
.then(()=>coinMarketData.updateCoinMarketData(db))
.then(()=>addRates(db));
If your update functions could be rewritten to return the db after completing, then you could rewrite the calls like so, point free style:
updateGdax(db)
.then(updateBitstamp)
.then(updateBitfinex)
.then(updatePoloniex)
.then(coinMarketData.updateCoinMarketData)
.then(addRates);
Each function, would then look something like this:
function updateGdax(db) {
return db.doSomething().then(()=> db)
}
Follow that pattern, and you have yourself some nice looking javascript.
And have a look at the new async/await, included in nodejs 8. It is much more intuitive:
async function main() {
await updateGdax(db)
await updateBitstamp(db)
await updateBitfinex(db)
await updatePoloniex(db)
await coinMarketData.updateCoinMarketData(db)
await addRates(db)
}
main().catch(e => console.error(e))
Try below approach,
updateGdax(db)
.then(function(){
return updateBitstamp(db)
}).then(function (){
return updateBitfinex(db);
}).then(function() {
return updatePoloniex(db);
}).then(function(){
return coinMarketData.updateCoinMarketData(db)
}).then(function(){
return addRates(db);
}).catch(function(err){
console.log(err);
});
Hope this will work. If any of the function is returning any value and if you want to use it in subsequent function the pass that value in following function() used inside then. Refer : https://strongloop.com/strongblog/promises-in-node-js-an-alternative-to-callbacks/

Wrapping promise in async/await

I'm struggling a bit with async/await and returning a value from a Promise.
function test () {
return new Promise((resolve, reject) => {
resolve('Hello')
})
}
async function c() {
await test()
}
As I understood things I should be able to get a value by doing:
console.log(c())
But clearly I am missing a point here as this returns a promise. Shouldn't it print "hello"? On a similar note I am unclear as to whether a callback needs to be converted to a promise before wrapping it in async/await?
I am missing a point here as this returns a promise. Shouldn't console.log(c()) print "hello"?
No, async functions always return promises. They're not magically running asynchronous code synchronously - rather the reverse, they turn synchronous-looking code (albeit speckled with await keywords) into asynchronously running one.
You can get the result value inside the asynchronous function:
async function c() {
const result = await test()
console.log(result);
return 'World';
}
c().then(console.log);
I am unclear as to whether a callback needs to be converted to a promise before wrapping it in async/await?
Yes, you can await only promises. See How do I convert an existing callback API to promises? for how to do the conversion.
Async functions return a Promise. If the function throws an error, the
Promise will be rejected. If the function returns a value, the Promise
will be resolved.

NodeJS callback sequence

Folks,
I have the following function, and am wondering whats the correct way to call the callback() only when the database operation completes on all items:
function mapSomething (callback) {
_.each(someArray, function (item) {
dao.dosomething(item.foo, function (err, account) {
item.email = account.email;
});
});
callback();
},
What I need is to iterate over someArray and do a database call for each element. After replacing all items in the array, I need to only then call the callback. Ofcourse the callback is in the incorrect place right now
Thanks!
The way you currently have it, callback is executed before any of the (async) tasks finish.
The async module has an each() that allows for a final callback:
var async = require('async');
// ...
function mapSomething (callback) {
async.each(someArray, function(item, cb) {
dao.dosomething(item.foo, function(err, account) {
if (err)
return cb(err);
item.email = account.email;
cb();
});
}, callback);
}
This will not wait for all your database calls to be done before calling callback(). It will launch all the database calls at once in parallel (I'm assuming that's what dao.dosomething() is). And, then immediately call callback() before any of the database calls have finished.
You have several choices to solve the problem.
You can use promises (by promisifying the database call) and then use Promise.all() to wait for all the database calls to be done.
You can use the async library to manage the coordination for you.
You can keep track of when each one is done yourself and when the last one is done, call your callback.
I would recommend options 1. or 2. Personally, I prefer to use promises and since you're interfacing with a database, this is probably not the only place you're making database calls, so I'd promisify the interface (bluebird will do that for you in one function call) and then use promises.
Here's what a promise solution could look like:
var Promise = require('bluebird');
// make promise version of your DB function
// ideally, you'd promisify the whole DB API with .promisifyAll()
var dosomething = Promise.promisify(dao.dosomething, dao);
function mapSomething (callback, errCallback) {
Promise.all(_.map(someArray, function(item) {
return dosomething(item.foo).then(function (account) {
item.email = account.email;
});
}).then(callback, errCallback);
}
This assumes you want to run all the DB calls in parallel and then call the callback when they are all done.
FYI, here's a link to how Bluebird promisify's existing APIs. I use this mechanism for all async file I/O in node and it saves a ton of coding time and makes error handling much more sane. Async callbacks are a nightmare for proper error handling, especially if exceptions can be thrown from async callbacks.
P.S. You may actually want your mapSomething() function to just return a promise itself so the caller is then responsible for specifying their own .then() handler and it allows the caller to use the returned promise for their own synchronization with other things (e.g. it's just more flexible that way).
function mapSomething() {
return Promise.all(_.map(someArray, function(item) {
return dosomething(item.foo).then(function (account) {
item.email = account.email;
});
})
}
mapSomething.then(mapSucessHandler, mapErrorHandler);
I haven't tried Bluebird's .map() myself, but once you've promisified the database call, I think it would simplify it a bit more like this:
function mapSomething() {
return Promise.map(someArray, function(item) {
return dosomething(item.foo).then(function (account) {
item.email = account.email;
});
})
}
mapSomething.then(mapSucessHandler, mapErrorHandler);

node kriskowal/q promise stack errors on chaining promises

The following code errors out on the first .then with:
/Users/danielbyrne/working/mite_npm/mite.js:48
.then(configMan.validateSettings(parsedData))
ReferenceError: parsedData is not defined
I don't understand why this code is failing.
The call:
parseConfigurationFile(path.join(__dirname,'file.config'))
.then(validateSettings(parsedData));
The functions it calls:
function parseConfigurationFile(fileName) {
var readFile = q.nfbind(fs.readFile);
readFile(fileName,"utf-8")
.then(function(data) {
var deferred = q.defer();
// Return the Config 'settings' in JSON
deferred.resolve(JSON.parse(data));
return deferred.promise;
});
}
function vaidateSettings (data) {...}
The only way this works is if I change the function validateSettings to an anonymous function and place it inline like this :
parseConfigurationFile(path.join(__dirname,'file.config'))
.then(function(parsedData){...});
Why can i not chain named functions in this manner?
Your validateSettings call should be like this:
parseConfigurationFile(path.join(__dirname,'file.config'))
.then(validateSettings);
The reason is that the validateSettings needs to be referenced as a function and the .then will invoke that function with the correct parameter. Doing it the way you are doing it, you receive a reference error because parsedData is not available at the time the function call is bound.

Resources