I'd like to define a module which computes a new dependancy, fetches it and then returns the result. Like so:
define(['defaults', 'get_config_name'], function(defaults, get_config_name) {
var name = get_config_name();
var config;
require.synchronous([configs / '+name'], function(a) {
config = defaults.extend(a);
});
return config;
});
Is there a way to do this or a better way to attack this problem?
You may try to use synchronous RequireJS call require('configs/'+get_config_name()), but it will load a module synchronously only if it is already loaded, otherwise it will throw an exception. Loading module/JavaScript file synchronously is technically impossible.
UPD: It's possible (see Henrique's answer) but highly unrecommended. It blocks JavaScript execution that causes to freezing of the entire page. So, RequireJS doesn't support it.
From your use case it seems that you don't need synchronous RequireJS, you need to return result asynchronously.
AMD pattern allows to define dependencies and load them asynchronously, but module's factory function must return result synchronously. The solution may be in using loader plugin (details here and here):
// config_loader.js
define(['defaults', 'get_config_name'], function(defaults, get_config_name) {
return {
load: function (resourceId, require, load) {
var config_name = 'configs/' + get_config_name();
require([config_name], function(config) {
load(defaults.extend(config));
})
}
}
});
// application.js
define(['config_loader!'], function(config) {
// code using config
});
If get_config_name() contains simple logic and doesn't depend on another modules, the better and simpler is calculating on the fly paths configuration option, or in case your config depends on context - map configuration option.
function get_config_name() {
// do something
}
require.config({
paths: {
'config': 'configs/' + get_config_name()
}
});
require(['application', 'defaults', 'config'], function(application, defaults, config) {
config = defaults.extend(config);
application.start(config);
});
Loading JavaScript synchronously is NOT technically impossible.
function loadJS(file){
var js = $.ajax({ type: "GET", url: file, async: false }).responseText; //No need to append
}
console.log('Test is loading...');
loadJS('test.js');
console.log('Test was loaded:', window.loadedModule); //loadedModule come from test.js
Related
I have some specs that are using the same functions, I would like to make one single file only for functions and read from this file while executing my scripts, would be that possible? if so.. how to do that?
During google searchers I found the "exports" to add in config file but didn't work (also I don't know how to call it from the config)
For example, I would like to add 2 functions in my config file (or separated file only for functions) and during any point of my execution, call it from the spec file:
function loginAdminUser(userElement, passWordElement, userName, password){
var loginButton = element(by.id('logIn'));
browser.get('https://( ͡° ͜ʖ ͡°).com/');
userElement.sendKeys(userName);
passWordElement.sendKeys(password);
loginButton.click();
}
function accessHistoryViewDetail(){
menuForViews.then(function(selectview) {
selectview[3].click();
browser.sleep(500);
});
}
1 - How can I do that? (using "Suites" would be an option?)
2 - How to call them in my specs?
Thank you and have a good day!
As far as I know you cannot add utility functions that you want to use in your tests in the config file. The options in the config file are generally for setting up the testing environment.
You can however put your functions in a separate file and import that to use the functions. Below is an example of how to do that using js and Node's module exports, you can do something similar with ts using classes.
// utils.js
function loginAdminUser(userElement, passWordElement, userName, password){
var loginButton = element(by.id('logIn'));
browser.get('https://( ͡° ͜ʖ ͡°).com/'); // nice Lenny face :)
userElement.sendKeys(userName);
passWordElement.sendKeys(password);
loginButton.click();
}
function accessHistoryViewDetail() {
menuForViews.then(function(selectview) {
selectview[3].click();
browser.sleep(500);
});
}
module.exports = {
loginAdminUserloginAdminUser: loginAdminUser,
accessHistoryViewDetail: accessHistoryViewDetail
}
Then in your spec file
import * as utils from './utils.js';
...
it('should ...', () => {
...
utils.accessHistoryViewDetail();
...
});
});
I hope that helps.
I have an ExtJS 5.1.2 app that utilizes throughout the app a global config set of parameters defined in app_dir/app/Application.js, that looks like:
launch: function () {
Ext.Loader.setConfig({enabled: true});
// Static parameters
cardioCatalogQT.config = {
mode: 'test', // switch to control use of staging or production server
//protocol: 'https://',
protocol: 'http://',
//host: 'production_server',
//host: 'test_server,
host: '127.0.0.1:5000',
apiGetQ: '/get_query/',
//apiGetQ: '/api/get_query/',
apiWriteQ: '/remote_query_put',
apiReadQ: '/remote_query_get',
//apiMedsMenu: '/api/meds',
//apiMedsMenu: '/meds',
remove: 'none'
};
// TODO - Launch the application
Ext.onReady(function () {
});
}
This way, I only have one place to change the parameters that make up the url in Ajax calls, (in this case protocol, host and apiGetQ, for example give mr the ability to set url = cardioCatalogQT.config.protocol + cardioCatalogQT.config.host + cardioCatalogQT.config.apiGetQ), in one place to change the server address from development -> testing -> production, instead of having to find all references throughout the app.
However, due to the way that the ExtJs loads, I cannot use these config parameters in data stores that use rest proxies, since these stores seem to load before items in the Ext.Loader.
For example, I have the following store:
Ext.define('cardioCatalogQT.store.Diagnoses', {
extend: 'Ext.data.Store',
alias: 'store.Diagnoses',
config:{
model: 'cardioCatalogQT.model.Diagnosis',
storeId: 'Diagnoses',
autoLoad: true,
proxy: {
type: 'rest',
url: 'http://127.0.0.1:5000/menu/diagnoses',
//url: 'http://test_server/menu/diagnoses',
//url: 'https://prod_server/api/menu/diagnoses',
reader: {
type: 'json',
rootProperty: 'menu_test'
}
}
}
});
So, when I change from testing to development environments, for example, I have to explicitly change the n different references for url in my n stores that have rest proxies.
Is there a way to define a config object so that I can use it for these stores? I looked at some examples of a preloader, but this did not seem to have any use cases documented for a global config object, also I had tried implementing a loadmask in a preloader, but it really screwed with the behavior of my app.
I use to do like #Alexander propose, however I'll prefer the singleton way. More ExtJs/MVC like.
So just to complete, I share my version:
/**
* #class
*/
Ext.define("MyApp.config.Config", {
alternateClassName: [
'MyApp.config'
],
singleton: true,
constant: {
// ... whatever constant you need to put here
},
constructor: function() {
var constant = this.constant;
//
// here, if you need to process some stuff
// for example calculate some constant
// which depend of other constant
//
return constant;
}
});
Require in your app
// Be sure to require your class prior
// to your app classes
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
requires: [
'Ext.app.*',
// ext stuff ...
'MyApp.config.Config',
// myApp stuff ...
]
// ...
});
Example usage:
Ext.define('MyApp.store.MyStore', {
// ...
proxy: {
type: 'rest',
url: MyApp.config.remoteUrl
}
})
We had similar issues, so we have put our global ConnectionSettings object into a script tag that is in index.html, before Ext.
<script type="text/javascript">
ConnectionSettings = {
...
...
};
</script>
<!-- The line below must be kept intact for Sencha Cmd to build your application -->
<script id="microloader" ...
That way, the object is available wherever we need it in our Ext code.
I have a model called Instance which works fine.
define([], function(){
return Backbone.Model.extend({
urlRoot:'/api/Instances',
parse:function(content){
return content.data;
}
});
});
My REST at here
http://localhost:3000/api/Instances/1
returns this
{"status":"success","data":{"id":1,"name":"bangladesh","write":null,"read":null,"createdAt":"2015-09-01T23:03:16.000Z","updatedAt":"2015-09-01T23:03:16.000Z","UserId":1}}
hence the parse function in my model. All good so far.
If I just call
http://localhost:3000/api/Instances
Then I get a block of all my records,
{"status":"success","count":212,"data":[
{"id":1,"name":"bangladesh","write":null,"read":null,"createdAt":"2015-09-01T23:03:16.000Z","updatedAt":"2015-09-01T23:03:16.000Z","UserId":1},
{"id":2,"name":"abqride","write":null,"read":null,"createdAt":"2015-09-01T23:03:58.000Z","updatedAt":"2015-09-01T23:03:58.000Z","UserId":1},
....
And my collection code is just this
define(['models/instance.js'], function(Model){
return Backbone.Collection.extend({
url:'/api/Instances',
model:Model,
parse:function(content){
return content.data;
}
})
});
The above code for the Collection will create 212 models. I've checked that with an initialise function in the model just to see if it was being called OK with the right data, and it is.
But in my view code when I go
this.collection.each(function(model) {
console.log("model id="+model.get("id")+" count="+count++);
out+=model.get("id")+"="+model.get("name")+"<br>";
});
there's nothing in these models, but there are 212 of them, I just get "undefined=null" 212 times.
I can see three options, two of which involve customizing the use of Backbone: 1. Calling collection.sync manually and then executing custom code afterward, 2. Passing a custom option in the initial collection.fetch() and looking for it in the Model parse() method.
These two options don't solve the problem at the source, however, since the concern is at the initial response level. In order to apply a response-level filter to your data, try overriding Backbone.ajax() before starting your application:
Backbone.ajax = function () {
var settings = arguments[1] || arguments[0]; // jQuery.ajax(url[, settings])
var success = settings.success;
settings.success = function (data, status, xhr) {
if (success) { success(data.data, status, xhr); }
};
return Backbone.$.ajax.apply(Backbone.$, arguments);
};
I'm using karma to run tests on an angularjs application.
There are a couple JavaScript functions that I would like to run at start-up, but they need to be dynamically created based on some system data. When running the app, this is handled with node.
Is there any way to create a script as a var and pass it to the files: [] rather than just using a pattern to load an existing file?
I can make this work by creating the file, saving it to disk then loading it normally, but that's messy.
You can create your own karma preprocessor script.
For a starting point use the following as example:
var fs = require('fs'),
path = require('path');
var createCustomPreprocessor = function (config, helper, logger) {
var log = logger.create('custom'),
// get here the configuration set in the karma.conf.js file
customConfig = config.customConfig || {};
// read more config here in case needed
...
// a preprocessor has to return a function that when completed will call
// the done callback with the preprocessed content
return function (content, file, done) {
log.debug('custom: processing "%s"\n', file.originalPath);
// your crazy code here
fs.writeFile(path.join(outputDirectory, name), ... , function (err) {
if (err) {
log.error(err);
}
done(content);
});
}
};
createCustomPreprocessor.$inject = ['config', 'helper', 'logger'];
module.exports = {
'preprocessor:custom': ['factory', createCustomPreprocessor]
};
Add a package.json with the dependencies and serve it as a module. ;)
For more examples have a look to more modules here: https://www.npmjs.org/search?q=karma%20preprocessor
I am building a small app primarily with socket io, however with a few things from expressjs.
One function of the socket io piece is to send an email when a certain event occurs. I've got this working fine with node_mailer.
The problem I'm running into is that I want to use the express view engine to render the emails from template files. The render method seems to be explicitly attached to the res object prototype.
What I've done feels pretty dirty:
// setup express server
var render;
app.get('/', function (req, res) {
if (typeof render == 'undefined') render = res.render;
res.end('Welcome to app');
});
// socket io code
socket.on('event', function (data) {
var email_content;
render('template', {}, function (err, result) { email_content = result; });
});
Is there a better way to gain access to expressjs's components outside the context of an http request, or even a better way to approach this problem? I tried rigging up a call to the exported express.view.compile function but that both didn't work and seemed like a high hoo
Here is where the information you seek comes from:
https://github.com/Ravelsoft/node-jinjs/wiki
With templates as modules
To have node load your templates as if they were modules, you first have to register your module extension :
require("jinjs").registerExtension(".tpl");
If you want your file to be transformed prior to being submitted to jinjs, you can pass a callback ;
var pwilang = require("pwilang");
require("jinjs").registerExtension(".pwx", function (txt) {
return pwilang.parse(txt);
});
You can now write this to user Jin:
var my_template = require("./mytemplate");
var context = { foo: "foo", bar: "bar" };
var result = my_template.render(context);
Because you are sticking Jin into express (as opposed to making express work with Jin) this is your best option. The res variable is only available in the route callback.
On express 3.x there is the alias app.render
// socket io code
socket.on('event', function (data) {
var email_content;
app.render('template', {}, function (err, result) { email_content = result; });
});