requireJS require function has a module name without a definition - javascript

I am trying to understand this piece of code
require(['mifosXComponents'], function (componentsInit) {
componentsInit().then(function(){
require(['test/testInitializer'], function (testMode) {
if (!testMode) {
angular.bootstrap(document, ['MifosX_Application']);
}
});
});
});
The code is at mifosX client code. I believe this is the entry point of the mifosX web client software. I am really confused by the require syntax here. All the online sample code I have seen is like require(["a", "b"], function (a, b){});. In the other words, the parameter list inside the function() are all listed inside the dependence [] right before it. However the code I pasted above has componentsInit inside the function(). And I could not find any place in the source code tree that componentsInit gets defined.....
What I am trying here is to understand the code logic flow of mifosX. I am new to Javascript and RequireJS. Please help me understand this if you know what's going on here. Thanks in advance!

Here is your code with some comments which will clarify:
// in the first line you are requiring a module with id `mifosXComponents`
// which then is passed to the callback as `componentsInit`
require(['mifosXComponents'], function (componentsInit) {
// seems that `componentsInit` is a function which returns a Promise object,
// so your are passing a callback to it to execute it after its fulfilment
componentsInit().then(function(){
// when the promise is fulfilled, you are requiring another module
// with id `test/testInitializer` which is passed to callback as `testMode`
require(['test/testInitializer'], function (testMode) {
// next lines are pretty simple to understand :)
if (!testMode) {
angular.bootstrap(document, ['MifosX_Application']);
}
});
});
});
About Promise you can read here: What does the function then() mean in JavaScript?

Related

Trouble understanding the requireJS require() function

I'm new to Javascript and I'm having troubles understanding the following piece of code. I have read this post (https://stackoverflow.com/a/60669635/9867856) which suggests that mifosXComponents.js and mifosXStyles.js are being passed as arguments into the function function(componentsInit){...}, but isn't componentsInit a single function that returns a promise? How come two .js files are converted into a function? I'm confused.
require(['mifosXComponents.js', 'mifosXStyles.js'], function (componentsInit) {
componentsInit().then(function(){
require(['test/testInitializer'], function (testMode) {
if (!testMode) {
angular.bootstrap(document, ['MifosX_Application']);
}
});
});
});
If you require two modules (as per example) then RequireJS will:
load them async;
load their dependencies;
inject the modules to you callback, each as separate argument.
So you have a mistake in your code, your callback will receive actually two arguments, so you need to have two parameters:
// require two modules async,
// when they are loaded,
// they are injected to your callback
require(['mifosXComponents.js', 'mifosXStyles.js'], function (mifosXComponents, mifosXStyles) {
// now you can use both modules,
// seems that first one is a function which returns promise,
// but I have no idea what is the second one :)
mifosXComponents().then(function(){
require(['test/testInitializer'], function (testMode) {
if (!testMode) {
angular.bootstrap(document, ['MifosX_Application']);
}
});
});
});

passing variables through callback functions in node.js

I posted this question yesterday but I guess I just confused everyone. I got responses like "what exactly is your question?" So I am expanding and reposting today.
The following node.js snippet is from the file "accounts.js" which is in an ETrade api library that exists in the path /lib. It should return json containing data about the accounts of the authenticated user. The authentication part is working great. I'm confused about what exactly is being done in the last line of this function:
this._run(actionDescriptor,{},successCallback,errorCallback);
Ten years ago (the last time I was coding), we didn't have the construct "this" and I haven't a clue about "_run" and Google searches have not been helpful. Here is the function.
exports.listAccounts = function(successCallback, errorCallback) {
var actionDescriptor = {
method: "GET",
module: "accounts",
action: "accountlist",
useJSON: true,
};
this._run(actionDescriptor, {}, successCallback, errorCallback);
};
I understand that the function is accessed with "et.listAccounts ...." but then my understanding goes all to hell. It's pretty obvious that a get is being executed and json data returned. It's also obvious that the result is passed back through the successCallback.
In my app.js file, I have the following:
var etrade = require('./lib/etrade');
var et = new etrade(configuration);
Can someone please suggest a snippet to be used in app.js that will output the accounts data to the console?
It seems like the json data must be passed back through the successCallback but I'm lost on how to access it on the app.js side.
Suppose in app.js I want to put the accounts data in a variable called myAccounts. The exports.listAccounts function does not specify a return value, so I doubt I can do var myAccounts = et.listAccounts(). Likewise, myAccounts will be undefined if I try to do this: et.listAccounts(){myAccounts, error}. Finally, the listAccounts function contains two possible variable names I could use, "accounts" and "accountlist" but these turn out to be undefined at app.js.
When I put a function in successCallback in app.js to write a generic message to the console, the message appears in the log so I know I am making it into the listAccounts function and back successfully. In this case, the log also shows
"Request: [GET]: https://etwssandbox.etrade.com/accounts/sandbox/rest/accountlist.json"
From this I deduce that the data is actually being returned and is available at that end point.
Ten years ago (the last time I was coding), we didn't have the construct "this" and I haven't a clue about "_run"
this refers to the current object, further reading here. _run is just what they chose to call the function.
I have no experience with this module, but with a cursory glance at the git repo I suspect you will want to expand your app.js like so:
et.listAccounts(function(response) {
console.log(response);
});
In javascript functions are first order and so can be passed around like variables see here. listAccounts wants a function passed to it, and when it is complete it will call it with one parameters, as can be seen in etrade.js.
There is also the function errorCallback which is much the same but is called on an error. You could expand the above snippet like so:
et.listAccounts(function(response) {
console.log(response);
}, function(error) {
console.log(error);
});

Require JS callback argument undefined

First off, I'm pretty new to Require JS, and I haven't done my fair share of reading the docs. Kind of just shooting from the hip here.
But this is functionality that, should work. Well as far as I've read.
I have a hashed URL, say at this stage it's #index.
And then I have the equivalent js page under /javascript/pages/index.js.
As you would figure, I'm trying to load these pages "dynamically".
However, my callback functions page parameter is undefined.
require(['javascript/pages/' + page],
function(page) {
var constructedPage = new page();
});
All Pages are "classes" function index(){}
In the meanwhile, I'll start reading up on the docs a bit more.
If you want to use objects/variables/etc created in the index.js within the callback of require(), you have to use a define() call to specify that object.
index.js
define(function(){
// create an object with constructor
function myPage(){
}
// some more code adding to the prototype
// return the actual object
return myPage;
});
Then you can use that object like you did in your code.
Note: That define() call may have dependencies of its own. Omitted here for simplicity's sake.

Deps autorun in Meteor JS

Decided to test out Meteor JS today to see if I would be interested in building my next project with it and decided to start out with the Deps library.
To get something up extremely quick to test this feature out, I am using the 500px API to simulate changes. After reading through the docs quickly, I thought I would have a working example of it on my local box.
The function seems to only autorun once which is not how it is suppose to be working based on my initial understanding of this feature in Meteor.
Any advice would be greatly appreciated. Thanks in advance.
if (Meteor.isClient) {
var Api500px = {
dep: new Deps.Dependency,
get: function () {
this.dep.depend();
return Session.get('photos');
},
set: function (res) {
Session.set('photos', res.data.photos);
this.dep.changed();
}
};
Deps.autorun(function () {
Api500px.get();
Meteor.call('fetchPhotos', function (err, res) {
if (!err) Api500px.set(res);
else console.log(err);
});
});
Template.photos.photos = function () {
return Api500px.get();
};
}
if (Meteor.isServer) {
Meteor.methods({
fetchPhotos: function () {
var url = 'https://api.500px.com/v1/photos';
return HTTP.call('GET', url, {
params: {
consumer_key: 'my_consumer_key_here',
feature: 'fresh_today',
image_size: 2,
rpp: 24
}
});
}
});
}
Welcome to Meteor! A couple of things to point out before the actual answer...
Session variables have reactivity built in, so you don't need to use the Deps package to add Deps.Dependency properties when you're using them. This isn't to suggest you shouldn't roll your own reactive objects like this, but if you do so then its get and set functions should return and update a normal javascript property of the object (like value, for example), rather than a Session variable, with the reactivity being provided by the depend and changed methods of the dep property. The alternative would be to just use the Session variables directly and not bother with the Api500px object at all.
It's not clear to me what you're trying to achieve reactively here - apologies if it should be. Are you intending to repeatedly run fetchPhotos in an infinite loop, such that every time a result is returned the function gets called again? If so, it's really not the best way to do things - it would be much better to subscribe to a server publication (using Meteor.subscribe and Meteor.publish), get this publication function to run the API call with whatever the required regularity, and then publish the results to the client. That would dramatically reduce client-server communication with the same net result.
Having said all that, why would it only be running once? The two possible explanations that spring to mind would be that an error is being returned (and thus Api500px.set is never called), or the fact that a Session.set call doesn't actually fire a dependency changed event if the new value is the same as the existing value. However, in the latter case I would still expect your function to run repeatedly as you have your own depend and changed structure surrounding the Session variable, which does not implement that self-limiting logic, so having Api500px.get in the autorun should mean that it reruns when Api500px.set returns even if the Session.set inside it isn't actually doing anything. If it's not the former diagnosis then I'd just log everything in sight and the answer should present itself.

Strange behavior with RequireJS using CommonJS sintax

I'm a strange behavior with RequireJS using the CommonJS syntax. I'll try to explain as better as possible the context I'm working on.
I have a JS file, called Controller.js, that registers for input events (a click) and uses a series of if statement to perform the correct action. A typical if statement block can be the following.
if(something) {
// RequireJS syntax here
} else if(other) { // ...
To implement the RequireJS syntax I tried two different patterns. The first one is the following. This is the standard way to load modules.
if(something) {
require(['CompositeView'], function(CompositeView) {
// using CompositeView here...
});
} else if(other) { // ...
The second, instead, uses the CommonJS syntax like
if(something) {
var CompositeView = require('CompositeView');
// using CompositeView here...
} else if(other) { // ...
Both pattern works as expected but I've noticed a strange behavior through Firebug (the same happens with Chrome tool). In particular, using the second one, the CompositeView file is already downloaded even if I haven't follow the branch that manages the specific action in response to something condition. On the contrary, with the first solution the file is downloaded when requested.
Am I missing something? Is it due to variable hoisting?
This is a limitation of the support for CommonJS-style require. The documentation explains that something like this:
define(function (require) {
var dependency1 = require('dependency1'),
dependency2 = require('dependency2');
return function () {};
});
is translated by RequireJS to:
define(['require', 'dependency1', 'dependency2'], function (require) {
var dependency1 = require('dependency1'),
dependency2 = require('dependency2');
return function () {};
});
Note how the arguments to the 2 require calls become part of the array passed to define.
What you say you observed is consistent with RequireJS reaching inside the if and pulling the required module up to the define so that it is always loaded even if the branch is not taken. The only way to prevents RequireJS from always loading your module is what you've already discovered: you have to use require with a callback.

Categories

Resources