Is it possible to call one function from another? (keeping separate files) - requirejs

I understand I can call any file at any time to call its functions (please correct me if I am wrong). I decided to test this by creating two modules (one and two), and calling function nested in two, from one. This works, but I'm unable to call function one from function two.
Main.js
requirejs.config({
baseUrl: "js"
});
require([
"script/one"
], function ($, $Ui, hBs, one) {
//works fine
one.get("I am the initiator");
});
one.js
define(['script/two'], function (two) {
var one = function () {
return {
get: function (msg) {
//works
console.log("get: " + msg);
//works fine
two.serve1("I am from one of one");
},
post: function (msg) {
// i am calling this method from two.js
console.log("post: " + msg);
two.serve2("i am from two of two");
}
}
}
return new one;
})
two.js
define([ 'require', 'script/one'], function (require,one) {
var two = function () {
one = require('script/one'); // throwing error as "Uncaught Error: Module name "script/one" has not been loaded yet for context: _"
return {
serve1: function (msg) {
console.log("2 in serve1 :" + msg)
// calling doesn't
one.post("initiated from one, called in two");
// throws "Uncaught TypeError: Cannot call method 'post' of undefined"
},
serve2: function (msg) {
console.log("2 in serve2 :" + msg)
}
}
}
return new two;
})
Why am I getting this error?

The problem is that you have create a circular dependency.
In that case only one of the injected values have the right value, the other one is just undefined. If you think about, its clear that this cant work, cause how should the one that is injected in the second one should know the second one as he is not created when the first one is created.
Fortunately there is a work around for this. Use the require function to load the dependency later:
define(["require", 'script/one'], function (require, one) {
var two = function () {
return {
serve1: function (msg) {
one = require('script/one');
console.log("2 in serve1 :" + msg)
// calling doesn't
one.post("initiated from one, called in two");
// throws "Uncaught TypeError: Cannot call method 'post' of undefined"
},
serve2: function (msg) {
console.log("2 in serve2 :" + msg)
}
}
}
return new two;
})
Note that you still need the reference to 'script/one' in the dependency array.

Related

.then() function is called before main function gets completed - Q.nfcall

A() function return promises after 1000 ms and throws an error. So, the next execution should be into catch. But, .then() function gets executed even after the main function throws an error.
Test.js
var Test1 = require("./Test1.js")
var Q = require('q');
var value = "Hardik";
var value1 = "Shah";
A()
.then(Test1.B(value, value1))
.catch(function(e){
console.log("In catch: ", e.message);
});
function A(){
console.log("In A function");
return Q.nfcall(AInner);
}
function AInner(callback){
setTimeout(function() {
callback({message: "Error from A Inner"});
}, 1000)
}
Test1.js
'use strict';
var Q = require("q");
module.exports = {B:B}
function B(value, value1){
console.log("In B function: ", value, " ", value1);
return Q.nfcall(BInner);
}
function BInner(callback){
console.log("In BInner function");
callback({message: "Error from BInner"});
}
Actual Output:
In A function
In B function: Hardik Shah
In BInner function
In catch: Error from A Inner
Expected Output:
In A function
Error from A Inner // After 1000 ms
I have solved issue by modifying below code: Works perfect
A()
.then(function(){
return Test1.B(value, value1)
}).then(function(data){
console.log("final data", data);
})
.catch(function(e){
console.log(e.message);
});
But, what is wrong with the above code?
Please give me a good explanation with the correct way to write code in the sequence of then rather than under then.
You can try here https://repl.it/#hrdk108/Hardik-Shah-Issue1 to reproduce an issue.
Issue is, you are invoking Test1.B(value, value1) inside then, rather than keeping it as callback. Because, once you used it as invocation, it started it's own promise chain. To fix it, change it to:
var Test1 = require("./Test1.js")
var Q = require('q');
var value = "Hardik";
var value1 = "Shah";
A()
.then(function() { Test1.B(value, value1) }) // note here
.catch(function(e){
console.log("In catch: ", e.message);
});
function A(){
console.log("In A function");
return Q.nfcall(AInner);
}
function AInner(callback){
setTimeout(function() {
callback({message: "Error from A Inner"});
}, 1000)
}
After a long brainstorm, I have figured out and it is just a silly mistake.
That Mistake is just because I invoked Test1.B() while defining
into then. Which is already answered in the above answer. So, One solution is I have already mentioned in the question.
Second solution:
The correct way to write a then sequence is:
Test1.B function without arguments:
A()
.then(Test1.B)
.catch(function(e){
console.log("In catch: ", e.message);
});
Test1.B with arguments: use bind
A()
.then(Test1.B.bind(null, value, value1))
.catch(function(e){
console.log("In catch: ", e.message);
});
Check here corrected example https://repl.it/#hrdk108/Hardik-Shah-Issue1
For Just FYI,
Actually, When you are using Q.nfcall you should take care of passing arguments design.
nfcall expects arguments provided individually
For Example:
Q.nfcall(B, value, value1);

Node.js - Unable to use callback in if statement

Hi I am trying to execute a callback in a if statement but I get "TypeError: callback is not a function"
This is my code:
socket.on('authenticate', function (data, callback) {
// this works
callback("false");
// this doesn't work
if (data == "abc") {
callback("true");
}
});
Always check if callable function is passed, at least just do if(callback)
in Your problem there may be situation that clientside not waiting for callback (done emit call without passing callback argument).
Try this solution:
socket.on('authenticate', function (data, callback) {
console.debug('socket authenticate:', data); // for debug purposes
if (data == "abc") {
if(callback) { // callback may not be passed
callback(null, true); // keep in mind in callbacks first argument is error second is result
}
return; // return will prevent execution to go down, because most of times used for resulting call.
}
if(callback) { // callback may not be passed
callback("Not authenticated", false);
}
});

(node:2684) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property 'then' of undefined

I am using .then for first time, instead of .then I use callback function.
Below is my code snippet:
phantom.create().then(function (ph) {
ph.createPage().then(function (page) {
page.open("http://codebeautify.org/xmlvalidator").then(function (status) {
page.render(base_pdf_path + lpnumber + '.pdf').then(function () {
console.log('PDF generated for waybill');
//Insert waybill url in db.
return waybill_url.insertWaybillUrl('Lpsimer', waybillUrl).then(function (waybill_inserted_resp) {
callback(null, true);
}).catch(function (error) {
callback(err_waybill_inserted);
});
});
});
});
});
The above function is calling a function which is as below, this is in another file and called properly filename is waybill.js:
var mongoose = require('mongoose');
var q = require('promised-io/promise');
var WaybillUrlSchema = new mongoose.Schema({
lpnumber: String,
url: String,
waybilltime: Date
});
module.exports = {
insertWaybillUrl: function (lpnumber, url) {
var defer = q.defer();
var waybill_insert = new waybill_url({
lpnumber: lpnumber,
url: url,
waybilltime: new Date()
});
//Save model to MongoDB
waybill_insert.save(function (err, inserted_waybill) {
if (err) {
return defer.reject(err);
}
else {
return defer.resolve(inserted_waybill);
}
});
}
};
Previously I was using this pattern to make callbacks and it was working fine:
waybill_url.insertWaybillUrl('Lpsimer', waybillUrl, function(err, success) {
if (err) {
} else {
}
)}
Now I have to use .then due to usage of phantom code to write PDF and it has made the job cumbersome.
Need suggestion on how I can make callbacks within callbacks.
UPDATE
phantom.create().then(function (ph) {
ph.createPage().then(function (page) {
page.open("http://codebeautify.org/xmlvalidator").then(function (status) {
page.render(base_pdf_path + lpnumber + '.pdf').then(function () {
//Insert waybill url in db.
waybill_url.insertWaybillUrl('Lpsimer', waybillUrl).then(function (waybill_inserted_resp) {
if (waybill_inserted_resp) {
callback(null, true);
}
}).catch(function (error_waybill_url_insert) {
console.log("Error in inserting waybill:" + err_waybill_inserted);
callback(error_waybill_url_insert);
});
}).catch(function (error_render) {
console.log("error_render");
callback(error_render);
});
}).catch(function (error_open) {
callback(error_open);
});
}).catch(function (error_create_page) {
callback(error_create_page);
});
}).catch(function (error_phantom_create) {
callback(error_phantom_create);
});
Now I have added catch for every then as suggested by rsp in his answer, but now I am getting error which I have catched and send to another callback:
Cannot read property 'then' of undefined
I am getting this error where I have added console.log("error_render");
that is where I am calling page.render function of phantom.
My requirement is simple. I want to generate a PDF file using phantom and then I just want to call another function which is in another file waybill_url, function name: waybill_url.insertWaybillUrl. But due to callbacks and asynchronous behaviour this simple calling of two functions is getting cumbersome.
Make sure that you use catch() and not only then() - or two arguments to then(). Otherwise you will not handle errors and you will get that warning - which will be an error, not a warning, in next versions of Node.
See this answer for more info about it:
Should I refrain from handling Promise rejection asynchronously?

bluebird promisifyAll() and then() not working together with node require

I'm using Promises for the first time, so please bear with me.
Basically, I'm not seeing the function in my .then() statement being called.
When I call t.t(), is it working correctly.
When I call t.tAsync(), t() is again called.
However the result isn't being passed into the then when I call t.tAync().then(console.log);
Here is my node module:
'use strict';
var t = function(){
console.log('inside t()');
return 'j';
};
module.exports = {
t: t
};
And here is my demo script:
'use strict';
require('should');
var Promise = require('bluebird');
var t = require('../src/t');
Promise.promisifyAll(t);
/*
Call t() once to demonstrate.
Call tAsync() and see t() is called
Call tAsync.then(fn), and then isn't called
*/
// this works as expected, calling t()
console.log('calling t()...' + t.t());
// this also works, calling t()
t.tAsync();
// the then() statement isn't called
t.tAsync().then(function(res){
// I expect this to be called
console.log('HHHUUUZZZAAAHHH' + res);
});
/*
Keep the script running 5 seconds
*/
(function (i) {
setTimeout(function () {
console.log('finished program');
}, i * 1000)
})(5);
And here is the output from the test:
inside t()
calling t()...j
inside t()
inside t()
finished program
Your then clause will never be called because the tAsync is expecting t to call the callback not return a value.
promisifyAll wraps Node.JS aysynchronous API's so the function it is wrapping needs to conform to the Node.JS callback signature:
function t(callback) {
callback(null, 'j');
}
However, I suspect based on your code that you do not want promiseifyAll but instead try() or method():
function t() {
return 'j';
}
Promise.try(t).then(function(result) {
console.log(result);
});
OR
var t = Promise.method(function() {
return 'j';
});
t().then(function(result) {
console.log(result);
});
For contrast the above is Bluebird.js specific. To perform this with generic Promises you would approach it one of two ways:
Using the Promise constructor:
function t() {
return new Promise(function(resolve, reject) {
resolve('j');
});
}
t().then(function(result) {
console.log(result);
});
Or, use the then chaining feature:
function t() {
return 'j';
}
Promise.resolve()
.then(t)
.then(function(result) {
console.log(result);
});
I was also not able to understand how "then" works. Below code example (just created to understand the flow) may help you:
var Promise = require('bluebird');
function task1(callback) {
setTimeout(function(){
console.log("taks1");
callback(null, "taks1");
}, 2000);
}
var taks1Async = Promise.promisify(task1);
taks1Async().then(function(result) {
console.log("Current task2, previous: " + result);
return "task2";
})
.then(function(result) {
console.log("Current task3, previous: " + result);
return "task3";
})
.catch(function(e) {
console.log("error: " + e);
});
console.log("Finished");

async/flow series on node.js

Consider this code:
var async = require('async');
var a = function()
{
console.log("Hello ");
};
var b = function()
{
console.log("World");
};
async.series(
[
a,b
]
);
Output is
Hello
Why is World not part of the output?
The async.series function passes one callback to each of the methods that must be called before the next one is called. If you change your functions a and b to call the function it will work.
function a(done){
console.log('hello');
done(null, null); // err, value
}
function b(done){
console.log('world');
done(null, null); // err, value
}
For each method called in series it is passed a callback method which must be run, which you are ignoring in your example.
The docs say:
tasks - An array or object containing functions to run, each function
is passed a callback(err, result) it must call on completion with an
error err (which can be null) and an optional result value.
The reason why your code is stopping after the first method is that the callback isn't being run, and series assumed an error occurred and stopped running.
To fix this, you have to rewrite each method along these lines:
var b = function(callback)
{
console.log("World");
callback(null, null) // error, errorValue
};

Resources