I wrote a piece of code to get CSS contents from a file and I want to get that data inside my helper function.
Server-side:
Meteor.methods({
'getCSS': function(filename) {
return '<style>' + Assets.getText('css/' + filename) + '</style>';
}
});
The css folder is located inside a private folder and consists of CSS files required for several pages. To my knowledge, the server-side code works correctly.
Client-side:
Template.home.helpers({
'css': function() {
var asyncFn = function(fn, cb) {
Meteor.call('getCSS', fn, function(err, res) {
console.log(res); // prints data correctly
cb && cb(null, res);
});
}
var syncFn = Meteor.wrapAsync(asyncFn);
var result = syncFn('home.css');
console.log(result); // undefined
return result;
}
});
After researching about how to use Meteor.wrapAsync this is the best solution that I could come up with. Not sure what I missed. I followed instructions from this blog.
You can't use Meteor.wrapAsync on the client, because on the server the illusion of synchronicity depends on Fibers and there is no such parallel on the client.
Fibers effectively inlines asynchronous functions so that other code can run while waiting for the callback. Among other things, it helps eliminate the callback pyramid of doom anti-pattern. However, it does make it harder to reason about your code since if Javascript objects are shared between fibers, you'll have to explicitly think about when your code might be yielding (voluntarily pre-empted, such as by making a database call).
In any case, it will probably be a while before something similar becomes available on the client - as you can see, Fibers is implemented as a C++ package for node and can't be done simply with Javascript, since it actually makes asynchronous function calls look synchronous.
In your case, the proper way of doing lazy loading of CSS (as opposed to just including it in the rest of the Meteor bundle) is to just put it in the public/ folder (or include from a package with {isAsset: true}) and use a <head> tag to load when you need it.
I don't exactly understand what you are trying to achieve here.
From my point of view, cas should be load and compile from the first loading. Don't think it is a good idea to load CSS on the fly... You'll not be able to unload.
If you're inside a tracker computation (i.e. into router for example, on rendered events) you could use ReactiveMethod package to have something like synchronous call. It use the tracker dependency to wait response.
Another thing, you could finally setup a server side route to served CSS files from private folder...
Here if you need it,
Cheers
Instead of storing the return value in a local variable, I used a Session. Now it works!
Template.home.helpers({
'css': function() {
Meteor.call('getCSS', 'home.css', function(err, res) {
Session.set('css', res);
});
return Session.get('css');
}
});
Related
I wrote a small express application and put my routes in a different file, routes.js:
module.exports = function(server) { // Server is my express object
server.get('/something', (req, res) => {
// Stuff
});
// Some other routes
}
To use them in my main file, server.js, I require them like this:
require('./routes')(server);
This works fine, but I've never seen a require without an assignment like
const bla = require('some-module');.
Is the way I'm using require here even valid and / or a good practice?
Is the way I'm using require here even valid
Of course.
You're just calling the function immediately instead of storing it in a variable.
a good practice?
That's a matter of opinion.
The basic thing require does is that it executes code written in the module. At the end this executed code might or might not return something. In your case it doesn't matter what this code returns, rather what matters is that this code is executed at least once.
Yes its a good practice.
I am using writeFileSync function to write a file locally, the file does get written, however, the callback function is never called.
I did some googling, some other post are having the issue that it's either 1) passing the content went wrong or 2) having two write function at the same time.
My problem is that there are some other places in my code that is using the writeFileSync, but they are on different routes (not sure if this is the right terminology, localhost:port#/differentroutes <- something like this). I am testing only on my own route so those write functions shouldn't even be called.
Here is my code:
if(!fs.existsSync(dir)){
fs.mkdirSync(dir)
}
//content is just a string var I swear it's just a string
fs.writeFileSync('./pages/SubmissionProcess.html',content,function(err){
if(err){
throw err
}else {
console.log("YES")
}
})
I never see this "YES" nor error in my console even tho the file is already written....
Write file sync doesn't take a callback :D
Take a look at the documentation :
https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options
The parameters are (path, data, options)
If you want to check if the file actually wrote, you can read file sync after writing it or check the last time the file was updated. Otherwise, you should try using the async approach.
All of the synchronous methods throw rather than passing an error to a callback.
try {
fs.writeFileSync('./pages/SubmissionProcess.html', content);
console.log('YES');
} catch (e) {
console.error(e);
}
Reworded:
A common pattern is to pass callback functions, such as with Mongoose's save (just for example and simplified - no error handling):
someMethod(req:Request, res:Response){
document.save( function(err){ res.status(200).send({message: 'all good'})});
}
I'd like to externalize the callback. You can do this this way:
var respond = function(err:any, res:Response){
res.status(200).send({message: 'all good'});
}
someMethod(req:Request, res:Response){
document.save( function(err){ respond(err, res)});
}
...but ideally I'd like to do this by just passing a function like respond without having to create a call back function to enclose respond. I wanted to know if this is possible. Since the anonymous function has access to res, I thought there might be some way to gain access to res in a function defined externally. It appears there is not a way to do this so I'll live with wrapping it.
My original question was trying to isolate the specific issue I was interested in - which is to gain access to the caller's variables implicitly. Doesn't seem like that is possible. Fair enough.
Original Question:
I'd like to externalize a bit of code I use frequently and I'm having trouble understanding closure in the context of a Typescript method. Take a look:
var test = function(){
console.log("Testing external: "+JSON.stringify(this.req.body));
}
class Handler {
static post(req: Request, res: Response){
(function(){
console.log("TESTING anon: "+JSON.stringify(req.body));
}) ();
test();
}
}
Besides the fact that this does nothing useful, in this bit of code, the inline anonymous function has access to the req object, but the test() function does not. this in test is undefined. Removing this to match the inline function doesn't help.
I believe if I were to bind on this for the call I'd just end up with a reference to the Handler class when I really want to bind on the post method.
My motivation for doing this is that I want to make a function that can be passed as a callback to a bunch of different request handlers. When I write the functions inline it all works, but when I externalize it I can't get a closure over the variables in the enclosing method. I've read "You Don't Know JS: this & Object Prototypes", and in pure Javascript I can manage to make these sorts of things work but I'm obviously doing something wrong here (it may not be Typescript related, maybe I'm just messing it up).
So bottomline - is there a way I can externalize the handler and get access to the method variables as if I were writing it inline? I could just create an inline anonymous function as the callback that calls the external function with all the variables I need, but I want to really understand what is happening here.
This is not an answer, but will hopefully give me enough feedback to give you one because its not at all clear what you're actually trying to accomplish here and whether or not you actually understand what the terms mean is an open question since you use them correctly one minute and sketchily the next.
var test = function(){
console.log("Testing external: " + JSON.stringify(this.req.body));
}
In strict mode this will throw an error, in sloppy it will try to access the req property of the global object which is not likely what you want.
(function(){
console.log("TESTING anon: "+JSON.stringify(req.body));
}) ();
The IFFE wrapper is completely unnecessary, it literally adds nothing to the party. So why include it?
static post(req: Request, res: Response){
console.log("TESTING anon: "+JSON.stringify(req.body));
test(); // is this the spot where you are 'in-lining?'
}
What I think you want is this:
var test = function(reqBody) {
console.log("Testing external: " + JSON.stringify(reqBody));
};
class Handler {
static post(req: Request, res: Response) {
test(req.body);
}
}
I'm trying to build several jsons using Modernizr at once, but it appears to break the scope of my function.
It's very hard to explain so have a look at this example, give it a go if you don't believe me:
[1,2,3,4,5].forEach(function(i){
require("modernizr").build({}, function (result) {
console.log(i);
});
})
outputs:
5
5
5
5
5
Instead of the expected 1, 2, 3, 4, 5, as would any similar function.
I have not come across this behaviour before in all my years of coding in ECMAScript like languages, and have built my project (and previous projects) around the idea that you cannot break a function's scope like that.
It breaks any system based on promises or even just simple callbacks.
It's baffled me all day, and I can't find an appropriate fix for it.
I'm have a very hard time even conceptualizing what it is that's causing this to happen.
Please help.
EDIT:
OK, it appears you're all hung up on the forEach...
Here's another example that will make it a little clearer:
function asd(i){
require("modernizr").build({}, function (result) {
console.log(i);
});
}
asd(1);
asd(2);
asd(3);
asd(4);
outputs
4
4
4
4
What on earth is happening?
The issue specific to Modernizr had to to with a global variable being clobbered.
the build command is basically a large requirejs configuration function, all powered by a large config object. There is some basic things that are true, always, that are established at the top of the function
{
optimize: 'none',
generateSourceMaps: false,
optimizeCss: 'none',
useStrict: true,
include: ['modernizr-init'],
fileExclusionRegExp: /^(.git|node_modules|modulizr|media|test)$/,
wrap: {
start: '\n;(function(window, document, undefined){',
end: '})(window, document);'
}
}
Then, since Modernizr works in both the browser and in node without changes, there needs to be a way for it to know if it should be loading its dependencies via the filesystem or via http. So we add some more options like basePath inside of a environment check
if (inBrowser) {
baseRequireConfig.baseUrl = '/i/js/modernizr-git/src';
} else {
baseRequireConfig.baseUrl = __dirname + '/../src';
}
At this point, the config object gets passed into requirejs.config, which wires up require and allows us to start calling build.
Finally, after all of that has been created, we have a build function that also ends up modifying the config object yet again for build specific settings (the actual detects in your build, regex to strip out some AMD crud, etc).
So here is a super simplified pseudocode version of what is ended up happening
var config = {
name: 'modernizr'
}
if (inBrowser) {
config.env = 'browser';
} else {
config.env = 'node';
}
requirejs.config(config);
module.exports = function(config, callback) {
config.out = function (output) {
//code to strip out AMD ceremony, add classPrefix, version, etc
callback(output)
}
requirejs.optimize(config)
}
spot the problem?
Since we are touching the .out method of the config object (whose scope is the entire module, and therefore its context is saved between build() calls) right before we run the asynchronous require.optimize function, the callback you were passing was rewriting the .out method every time build is called.
This should be fixed in a couple hours in Modernizr
The function block is called asynchronously, so this behavior is expected because this call is much slower than the walk of your foreach, so when you reach the function (result) {} block iis already five
Quite the same problem as described in Node.JS: How to pass variables to asynchronous callbacks? here and you should be able to use the same solution
[1,2,3,4,5].forEach(function(i){
(function(i) {
require("modernizr").build({}, function (result) {
console.log(i);
});
})(i);
})
untested but somethign like that should work
I have a NodeJS application and I want to execute some method for file validations but just one time (this method will validate some files under the node application).
Is there an elegant way to do this? Events?
The NodeJS documentation on modules states that:
Modules are cached after the first time they are loaded.
which you can take advantage of by adding static code to the module. Regardless of how many times the module is loaded, the static code will retain its state(/value).
You can use that state from a method to implement a method that can be called whenever you like -- at the best time during initialization -- but only ever be called once. This is pretty simple:
var called = false;
function checkFiles() {
if (called) return;
// Perform your validation
called = true;
}
module.exports = {
checkFiles: checkFiles
};
Because of the module caching, you can require this file in as many places as you need and it will still only execute once.
To invoke this function, you have a few options:
For a simple application, you can call the function from your main module (or function) and it will be invoked at that time. If the validation should be asynchronous, you can wrap your main method in a function and pass that to the validator as a callback.
//#! /bin/env node
var express = require('express');
var validator = require('./validator');
validator.checkFiles();
var app = express();
var server = app.listen(3000, function () {
...
});
For a more complicated application, you should call this function during your existing initialization routine (again, using callbacks as necessary).
If you have a nice modern promise-based initializer, you could simply add the validator as the first step of the chain.