I had a previous question Object [object Object] has no method 'test' Now the issue with object is gone but the call back is not working the console.log prints undefined
this.test = function(callback) {
callback('i am test');
};
var self = this;
module.exports.config = function (settings, callback) {
self.test(function(err,res){
console.log(res);
});
};
Please ignore as i am new to nodejs
this.test() expects a callback that will be passed a string as the first argument. You are giving it a callback function that uses the second argument, not the first argument. Since no second argument is passed to the callback, you get undefined for it.
Change your call from this:
self.test(function(err,res){
console.log(res);
});
to this:
self.test(function(err){
console.log(err);
});
Or, alternatively change the implementation of this.test() to pass a second argument to its callback.
this.test = function(callback) {
// pass two arguments to the callback
callback('i am test', 'this is me');
};
var self = this;
module.exports.config = function (settings, callback) {
self.test(function(err,res){
// now both arguments err and res are available here
console.log(res);
});
};
Related
I have a service which is calling a function, I am writing a test for that service and I need to stub the function inside that service, that function has callback instead of returning a promise. when I make the stub for that I and give dummy return but it hangs as service expects the callback,
here is my code for the test
describe('Testing Token Service', () => {
let _stub =null;
beforeEach(async()=>{
_stub = sinon.stub(tModel.prototype, "save")
})
afterEach(async()=>{
if(_stub){
_stub.restore()
}
})
it('testing function saveToken_mongo() ', (done) => {
_stub.returns(Promise.resolve( {'status' : 'true'} ))
token_service.saveToken_mongo({},function(err, data){
console.log(err, data)
done();
})
// done()
}); });
and here is the service function for which I am writing test
Service.prototype.saveToken_mongo = function(token, callback){
var _token = new tModel( token ) ;
_token.save(function(err, data){
if(err){
callback(err, null);
return ;
}
else{
callback(null, {'status':true})
return ;
}
}) }
I need to make dummy callback return from that function using stub.
stub.returns is used for ordinary function not for callback. Since save is callback function, we can use yields.
_stub.yields(null, {'status' : 'true'});
The first argument is for error value, and the second one is for data.
As reference:
https://sinonjs.org/releases/v7.1.1/stubs/#stubyieldsarg1-arg2-
It's a bit tricky, your callback is the saveToken_mongo param,
didn't test it but try:
_stub.returns(function(err, data){callback(null, {'status':true}) });
let me know if you got an error for the callback, you may try using this.callback instead
After the study, I reached the conclusion that there are 2 solutions to this problem.
1) according to deerawan we can use yields to replace callback of function, like this
_stub.yields(null, {'status' : 'true'});
for more detail https://sinonjs.org/releases/v7.1.1/stubs/#stubyieldsarg1-arg2-
2) use bluebird to promisify all methods which will change all methods response from the callback to promise then you can use Promise.returns, here is code
var Model = conn.model( name , ModelSchema);
var Promise = require('bluebird');
Promise.promisifyAll(Model);
Promise.promisifyAll(Model.prototype);
module.exports = Model;
Now you can use test as follows
let _stub = null;
var tModel = require('./../app/models/tokens') ;
beforeEach(async()=>{
_stub = sinon.stub(tModel.prototype, "save")
})
afterEach(async()=>{
if(_stub){
_stub.restore()
}
})
it('returns a Promise' ,async function(){
_stub.returns(Promise.resolve( {'status' : 'true & false'} ));
expect(token_service.saveToken_mongo({})).to.be.a("Promise")
})
I wrote test code for bluebird in Node.js like this:
var Promise = require(‘bluebird’)
var obj = {
func1: function () {
return ‘foo’
},
func2: function () {
return ‘bar’
}
}
console.log("==================================")
Promise.promisifyAll(obj)
obj.func1Async().then(function (result) {
console.log(result)
})
what i expected is to print the "foo", but actually nothing output.
is there something wrong?
After looking around for a while, it seems that Bluebird promisify works on node-style functions, which are as follows:
may accept 0..N parameters first
last parameter is always a callback
callback needs to be called with (error, data) params in that order.
So in your case, code should be:
var obj = {
func1: function (cb) { // note if you add params they need to be before cb and always passed when invoking the func1Async version
cb(null, 'foo'); // null => no error
},
func2: function (cb) {
cb(null, 'bar'); // null => no error
}
}
Then it works. Ugly - but it's how it should be.
I'm new to Node/Javascript and trying to grab a url audioLink by loading another url songLink. I would then add them to a new object rapSong. To achieve this I am using async series so that the calls will be happen asynchronously. I have tried other methods such as using async waterfall and just callbacks with no success.
audioLink is undefined unless I am within the getAudioLink function. Also the functions in the async.series do not run in the correct order. Any advice?
//for each song..
songLinkElem.each(function(i, s) {
var songName = StringUtils.removeWhiteSpacesAndNewLines($(s).children(".title_with_artists").text());
var songLink = $(s).attr("href");
var audioLink;
async.series([
function(callback){
function getAudioLink(songLink, callback){
request(songLink, function(err,resp,body){
$ = cheerio.load(body);
var audioElem = $(body).find(".audio_link > a");
var audioLink = audioElem.attr("href");
return callback(audioLink);
});
}
getAudioLink(songLink, function(resp){
audioLink = resp;
console.log("one");
})
console.log("two");
callback();
},
function(callback){
var rapSong = new Song(songName, artistLink, songLink, audioLink);
rapArtist.addSong(rapSong);
console.log("three");
callback();
}],
function(err, result){
console.log("four");
});
Within your first async.series function, you shouldn't call its callback until the callback for getAudioLink is called.
So move the code that follows the getAudioLink call inside its callback:
getAudioLink(songLink, function(resp){
audioLink = resp;
console.log("one");
console.log("two");
callback();
});
That way the async.series won't proceed until after audioLink is set.
I have this async function that I want to turn into a promise
var myAsyncFunction = function(err, result) {
if (err)
console.log("We got an error");
console.log("Success");
};
myAsyncFunction().then(function () { console.log("promise is working"); });
and I get TypeError: Cannot call method 'then' of undefined.
What is wrong with this code?
There are various ways in Q:
Q.nfcall(myAsyncFunction, arg1, arg2);
Q.nfapply(myAsyncFunction, [arg1, arg2]);
// Work with rusable wrapper
var myAsyncPromiseFunction = Q.denodeify(myAsyncFunction);
myAsyncPromiseFunction(arg1, arg2);
in Deferred implementation:
var myAsyncPromiseFunction = deferred.promisify(myAsyncFunction);
myAsyncPromiseFunction(arg1, arg2);
One notable difference: Wrappers as generated by Deferred additionally auto-resolve promises passed as an arguments, so you can do:
var readFile = deferred.promisify(fs.readFile);
var writeFile = deferred.promisify(fs.writeFile);
// Copy file
writeFile('filename.copy.txt', readFile('filename.txt'));
myAsyncFunction return nothing(undefined actually) in your code.
If you use whenjs, the normal way will be like this:
var myAsyncFunction = function() {
var d = when.defer();
//!!!do something to get the err and result
if (err)
d.reject(err);
else
d.resolve.(result);
//return a promise, so you can call .then
return d.promise;
};
Now you can call:
myAsyncFunction().then(function(result(){}, function(err){});
Using caolan's async library for node.js, I've been trying to call a function that uses async.series inside another function that uses async.series, but I still can't get the functions to run in the correct order, as detailed below:
The terminal output shows the second function being called before the first, for no apparent reason:
The "sys" module is now called "util". It should have a similar interface.
Starting the second step in the series
Value of b: undefined
Invoking the function firstStep
the value of toObtain is: [object Object]
And here's the corresponding source code:
var im = require('imagemagick');
var async = require('async');
var toObtain;
var b;
async.series([
function (callback) {
//It appears that this function is being invoked after the second function.
//Why is this happening?
firstStep();
callback();
},
function (callback) {
//Why is the output of this function being displayed BEFORE the output of the function above? It's the opposite of the order in which I'm calling the functions.
console.log("Starting the second step in the series");
console.log("Value of b: " + b);
}]);
function firstStep(){
async.series([
function (next) { // step one - call the function that sets toObtain
im.identify('kittens.png', function (err, features) {
if (err) throw err;
console.log("Invoking the function firstStep");
toObtain = features;
//console.log(toObtain);
b = toObtain.height;
next(); // invoke the callback provided by async
});
},
function (next) { // step two - display it
console.log('the value of toObtain is: %s',toObtain.toString());
}]);
}
After about an hour of experimentation, I got it to work properly. I simply modified the firstStep function so that it takes a callback function as a parameter, and calls the callback at the end of the firstStep function.
var im = require('imagemagick');
var async = require('async');
var toObtain = false;
var b;
async.series([
function (callback) {
firstStep(callback); //the firstStep function takes a callback parameter and calls the callback when it finishes running. Now everything seems to be working as intended.
},
function (callback) {
console.log("Starting the second step in the series");
console.log("Value of b: " + b);
}]);
function firstStep(theCallback){
async.series([
function (next) { // step one - call the function that sets toObtain
im.identify('kittens.png', function (err, features) {
if (err) throw err;
console.log("Invoking the function firstStep");
toObtain = features;
//console.log(toObtain);
b = toObtain.height;
next(); // invoke the callback provided by async
});
},
function (next) { // step two - display it
console.log('the value of toObtain is: %s',toObtain.toString());
theCallback();
}]);
}