I have project with 3 folders (I'm using gulp), which I don't need to compile. So, I need a task, which takes 3 folders "src/fonts", "src/libs" and "src/docs" as gulp.src() and just move them in dest/ folder. I don't need to do something with them, just move them after building.
My current attempt:
gulp.task('others', function () {
return gulp.src(['src/libs/**'], ['src/fonts/**'], ['src/docs/**'])
.pipe(gulp.dest('dist/'))
});
Using this code, task move only inner files and folders(need to be wrapped), and it take only "src/libs" as gulp.src()
Problem:
You're using gulp.src() wrong.
Explanation:
In the current state of your code, the following is happening:
['src/libs/**'] gets passed to globs property
['src/fonts/**'] gets passed to options property
['src/docs/**'] gets passed to NOTHING
The above explains why you're only seeing the files of src/libs being selected.
Thus:
gulp.src(['src/libs/**'], ['src/fonts/**'], ['src/docs/**'])
should be
gulp.src(['src/libs/**','src/fonts/**','src/docs/**'])
or (with a file wildcard *.*)
// something like this (its dirty as I'm writing this off the cuff)
// but you get the idea
var sources = [
'src/libs/**',
'src/libs/**/*.*',
...
];
gulp.src(sources)
Some More Information:
The docs specify the usage as such:
gulp.src(globs[, options])
where globs can only be a:
string => 'im/a/single/directory/or/file/s'
(a single) array object => ['dir1','dir2','dir3','etc']
and options, ... well, an options object (with defined values that you can supply)
options => { buffer: true, read: false, ... }
Related
I've started creating a Discord bot in Node.js using the Discord.js library. However, all the code is contained within a single index file.
How do I organize the commands and events each into separate files, and run them when needed?
An excellent, clean way to organize the code for your bot is to employ event and command handlers.
In simple terms.
You start out with a small index file to initialize the client and the rest of the code. An event handler keeps the files for each event, and calls on them when the event is emitted. Then, in your client's message event, you can avoid long if chains and switch/case altogether by running the code from the intended command's file.
What's a module?
The basic Node.js structure you'll need to understand is a module.
[A module is a] set of functions you want to include in your application.
Quoted from w3schools.com.
So, think of a module as a neatly taped up box containing pieces of code. You can take the package somewhere, open it up, and unpack the pieces. In JavaScript terms, you can require the module somewhere else in your program, and utilize the code contained within it. Modules can contain variables, classes, functions, etc. that you need to use throughout different locations across your code.
Working with modules and exports.
Now that you know what a module is, you have to understand how to work with them.
For the purpose of the handlers, you're only going to be using the exports property of the module object. By using require() for a module, module.exports is returned. Consider the following setups.
A single export.
Question.js
class Question {
constructor(author, details) {
this.author = author;
this.details = details;
this.answers = [];
}
}
module.exports = Question;
newQuestion.js
const Question = require('./Question.js');
const myQuestion = new Question('me', 'How to code event/command handlers?');
In Question.js, a new class, Question, is created and assigned to module.exports. Then, when Question.js is required in newQuestion.js, Question is declared as the exported class. It can be used just as usual.
Multiple exports.
Now, for example, if you needed to export multiple classes...
Posts.js
class Question {...}
class Answer {...}
module.exports = { Question, Answer };
// Alternatively...
// module.exports.Question = Question;
// module.exports.Answer = Answer;
newQuestion.js
const { Question } = require('./Posts.js');
const myQuestion = new Question(...);
In this way, module.exports is defined as an object, containing the created classes. This means that require() will return an object instead, so you can destructure the needed class from the object.
Creating the event handler.
You should start by creating a folder for your events, and create a file for each one. Name the files according to the name of the event. For example, for your client's message event, the file should be named message.js.
Setting up the event files.
Implementing what you now know about modules, you can code the event files. For example...
message.js
module.exports = (client, message) => {
// This code will be executed when
// the 'message' event is emitted.
};
Setting up the handler.
To make the actual handler, you can place the following code in a function to load events...
const requireAll = require('require-all'); // Don't forget to install!
const files = requireAll({ // Require all the files within your
dirname: `${__dirname}/events`, // event directory which have a name
filter: /^(?!-)(.+)\.js$/ // ending in '.js' NOT starting
}); // with '-' (a way to disable files).
client.removeAllListeners(); // Prevent duplicate listeners on reload.
// CAUTION: THIS REMOVES LISTENERS
// ATTACHED BY DISCORD.JS!
for (const name in files) { // Iterate through the files object
const event = files[name]; // and attach listeners to each
// event, passing 'client' as the
client.on(name, event.bind(null, client)); // first parameter, and the rest
// of the expected parameters
console.log(`Event loaded: ${name}`); // afterwards. Then, log the
} // successful load to the console.
Now, when your client emits one of the events you have a file for, the code inside of it is run.
Creating the command handler.
Just like for the event handler, you should start by creating a separate folder for your commands, and create files for each individual command.
Setting up the command files.
Instead of exporting just one function, you can export a "run" function and a configuration object.
help.js
module.exports.run = async (client, message, args) => {
// This code will be executed to
// run the 'help' command.
};
module.exports.config = {
name: 'help',
aliases: ['h'] // Even if you don't want an alias, leave this as an array.
};
Setting up the handler.
Just like the event handler, place this code in a function to load commands...
const requireAll = require('require-all'); // Using the same npm module...
const files = requireAll({ // Require all the files within your
dirname: `${__dirname}/commands`, // command directory which have a name
filter: /^(?!-)(.+)\.js$/ // ending in '.js' NOT starting
}); // with '-' (a way to disable files).
client.commands = new Map(); // Create new Maps for the corresponding
client.aliases = new Map(); // command names/commands, and aliases.
for (const name in files) { // Iterate through the files object
const cmd = files[name]; // and set up the 'commands' and
// 'aliases' Maps. Then, log the
client.commands.set(cmd.config.name, cmd); // successful load to the console.
for (const a of cmd.config.aliases) client.aliases.set(a, cmd.config.name);
console.log(`Command loaded: ${cmd.config.name}`);
}
In your client's message event, you can use the following code to run the commands...
const prefix = '!'; // Example
const [cmd, ...args] = message.content.trim().slice(prefix.length).split(/\s+/g);
const command = client.commands.get(cmd) || client.commands.get(client.aliases.get(cmd));
if (command) {
command.run(client, message, args);
console.log(`Executing ${command.config.name} command for ${message.author.tag}.`);
}
FAQ.
What if I have a database related or other variable I need to pass through events/commands?
For events, you can pass your variable in event.on(...), following client. Then in your actual events, your function must include that parameter after client.
For commands, you can pass your variable into the run function when calling it in the message event. Again, in your function, you need to include the properly placed parameter.
What if I want to have commands/events within subfolders?
Check out this answer to search recursively.
How do I use these handlers for a reload command?
If you placed the code for them inside of functions, you can set up a "reload" command that calls those functions, loading the events and commands again.
Related resources.
Node.js Documentation
MDN Documentation
W3Schools Tutorial
require-all Package
Discord.js Documentation
Edits...
client.removeAllListeners() will remove all listeners attached to the client, including those originating from client instantiation. This can cause voice connection related errors, specifically Voice connection not established within 15 seconds being thrown. To prevent this issue, keep track of every listener function and remove each individually using client.removeListener(listener).
I'm trying to understand module.exports better.
As I understand it, it can be used as a two way communication (you can send and receive data to the module.
However, this is not working as I expected:
File1.js:
var Test = require("./Balances")
Test.push(12)
Balances.js:
var arrays = [10, 11];
module.exports = arrays
File2.js:
var Test = require("./Balances")
setInterval(function(){console.log(Test)},2000)
What I want is to be able to add to the array from File1, and read the output in File2.
File2 reads the initial array just fine, but the value I push never shows in File2.
However, if I add a console.log(Test) in File1, that pushed value does appear there.
Upon rerunning File1, I don't however see [12, 12] , only [ 12 ], which means the first push never got written in the Balances array.
Any idea why?
When you import a variable from another javascript module, you get that variable by value, not by reference (you create a copy of the value at the given memory address, you don't simply get a pointer to that same exact variable). Therefore, you have only mutated the Test variable in File1.js; to reflect those changes in your console.log in File2.js you would have to re-export your mutated variable from File1.js and import that into File2.js, and then do the log.
Here is analysis of your code:
File1.js:
// creates copy of the `Balance.js` `arrays` variable
// stores value in new variable `Test`
var Test = require("./Balances") // => [10, 11]
// pushes 12 to the copy
Test.push(12) // => [10, 11, 12]
File2.js:
// creates copy of the `Balance.js` `arrays` variable
// stores value in new variable `Test`
var Test = require("./Balances") // => [10, 11]
// This interval does nothing. The fact is, the mutated
// `arrays` var from `File1.js` does not effect the
// `arrays` var in any other modules scope.
setInterval(function(){console.log(Test)},2000) // => [10, 11]
This is all assuming you have additional code not seen here that is required and executed from an entry point. As Thomas said in the comments, there is no state persisted between running individual scripts.
To accomplish what you're attempting in your post:
Balances.js:
var arrays = [10, 11]
module.exports = arrays
File1.js:
var test = require('./Balances')
test.push(12)
module.exports = test
File2.js:
var test = require('./File1')
function action() {
console.log(test)
}
module.exports = action
main.js (entry point):
var action = require('./File2')
action() // => [10, 11, 12]
run $ node main.js
Hope this helps!
It had to have never gotten pushed because you didn't actually require File1.js anywhere. This main.js works exactly as expected with the original File1.js, File2.js, and Balances.js files. (You probably wanted setTimeout, and as mentioned that had no effect anyhow, but it does work.)
require('./File1')
require('./File2')
Yes, modifying passed non-primitives updates the original item. They are not copied. Don't spend the next few years on a redundant construct to rebuild what is already happening.
Technically you can use modules like that, but I'd avoid that. Mutating state like that can lead to a lot of problems, especially if it is done in distributed modules.
And out of a sudden you have some error or unwanted behaviour that seems to come out of nowhere. Because its source is in an completely unrelated part of your app. Have fun, finding/debugging that.
I'd rather use modules as read-only sources for configs and stuff, or export a self-contained API that manages these mutations and everything else that happens in that module.
Back to you question
all you need is a common entry point that loads both modules in the same application.
That's probably ýour misconception. every time you call node ... you start a seperate application with seperate memory and state. It loads the files you tell it to, executes the code and eventually finishes. Like opening two sites in the browser, one loading File1, the other one loading File2.
So, you can create a common entry point like main.js
require("./File1");
require("./File2");
and then start the application at that common entry point node main.js
Or you can run node -i -r "./File1" -r "./File2" and start typing more JS.
So, I'm a big fan of creating global namespaces in javascript. For example, if my app is named Xyz I normally have an object XYZ which I fill with properties and nested objects, for an example:
XYZ.Resources.ErrorMessage // = "An error while making request, please try again"
XYZ.DAL.City // = { getAll: function() { ... }, getById: function(id) { .. } }
XYZ.ViewModels.City // = { .... }
XYZ.Models.City // = { .... }
I sort of picked this up while working on a project with Knockout, and I really like it because there are no wild references to some objects declare in god-knows-where. Everything is in one place.
Now. This is ok for front-end, however, I'm currently developing a basic skeleton for a project which will start in a month, and it uses Node.
What I wanted was, instead of all the requires in .js files, I'd have a single object ('XYZ') which would hold all requires in one place. For example:
Instead of:
// route.js file
var cityModel = require('./models/city');
var cityService = require('./services/city');
app.get('/city', function() { ...........});
I would make an object:
XYZ.Models.City = require('./models/city');
XYZ.DAL.City = require('./services/city');
And use it like:
// route.js file
var cityModel = XYZ.Models.City;
var cityService = XYZ.DAL.City;
app.get('/city', function() { ...........});
I don't really have in-depth knowledge but all of the requires get cached and are served, if cached, from memory so re-requiring in multiple files isn't a problem.
Is this an ok workflow, or should I just stick to the standard procedure of referencing dependencies?
edit: I forgot to say, would this sort-of-factory pattern block the main thread, or delay the starting of the server? I just need to know what are the downsides... I don't mind the requires in code, but I just renamed a single folder and had to go through five files to change the paths... Which is really inconvenient.
I think that's a bad idea, because you are going to serve a ton of modules every single time, and you may not need them always. Your namespaced object will get quite monstrous. require will check the module cache first, so I'd use standard requires for each request / script that you need on the server.
I am new to Javascript/backboneJS/RequireJS. In order to render my front end I have made one controller, one model and one view. Also, I have one dropdown in my html file.
So what I have done till now is in my html file at the END I have
require(['common'],function()
{
require(['jquery','fastclick','nprogress','charts','underscore','spinner'],function()
{
require(['firstDashboardController']);
});
});
So I am loading "firstDashboardController" and this controller loads all the modules accordingly and displays data in front end. So everything works fine.
Now I have a dropdown in the front end. When I select the dropdown, as per the id selected I want to retrieve the data. So I need to call "firstDashboardController" again so that everything gets rendered as per the new id that I have got.
So what am I suppose to do? Like do I need to UN-REQUIRE my "firstDashboardController" and then REQUIRE it again passing the new id. Because the controller is already loaded via Require beacuse I loaded it in my HTML file as mentioned above. But I need to load it again as per the new id selected it via dropdown. So how to go about it? Pleas help me. if any code snippet is required I can put that.
Code Snippet:
My Controller:
define(['backbone', 'firstSubViewModel','dropdownViewModel', 'dropdownModel'],
function(Backbone, firstSubViewModel, dropdownViewModel, dropdownModel) {
var ch = new dashboardModel.chart({});
if (localStorage.getItem('p_kt') && localStorage.getItem('p_acid') && localStorage.getItem('p_seid')) {
var data = {
tokenProp: localStorage.getItem('p_kt'),
accountIdProp: localStorage.getItem('p_acid'),
sessionIdProp: localStorage.getItem('p_seid')
};
$.when(
ch.fetch(data) // GETTING DATA FROM MODEL VIA AJAX CALL in my model.JS
).then(function() {
// Main Graph on Dashboard
new firstSubViewModel({
el: '#chartAnchor1',
model: ch
});
});});
I somehow need to call ch.fetch() again.
You aren't properly defining your controller. You currently have it as sort of a one-time setup method instead of something you can re-run later. Let's go step by step.
myLife.js:
define([], function() {
return "a complex series of failures";
});
By returning a value from define's callback, this defines that anytime I require "myLife", then it will provide "a complex series of failures" in the callback function. This is what Backbone and other AMD modules do to appear inside your code blocks. However, it only runs the contents once; and saves the result. So, this won't work:
incrementer.js:
var x = 0;
define([], function() {
x = x + 1;
return x;
});
(Trying to require incrementer would always give you "1".)
What you want to do is return a function - one you can re-run anytime.
incrementerV2.js:
define([], function() {
var x = 0;
return function() {
x = x + 1;
return x;
};
});
In any file, you can then have this:
require(['incrementerV2'], function(myIncr) {
myIncr(); // 1
myIncr(); // 2
});
...And, for the record, I would recommend having only one require statement in any given file whenever possible. You can add dependencies in that first-argument array if load order is important.
More commonly, people will have one module contain a self-defined object that has multiple functions in it, rather than the function I gave above. Returning and then using just one function is valid as well, depending on the use case. Any variable type works, but just remember it will always be the one and only same variable anytime you later need it.
Load Order
When the system retrieves myLife.js or incrementer.js above, there's an intermediate step before it actually runs the definition function we've defined. It will look at the first argument, the array of named dependencies, and figure out if there are still dependencies needed before it can run the function given. Example:
a.js: require(['b', 'c'], function(b, c) {
b.js: define(['c'], function(c) {
c.js: define([], function() {
a.js is requested first, but not run because it needs B and C. B loads next, but is ignored because C is not loaded. C runs, and then its return value is passed into A and B. This system is internally very smart, and should never request the same file twice or have conflicts if one file loads before another. You can use it much like imports in Java.
Also, let's say you only added 'c' in a.js so that b.js wouldn't crash, because it needs it loaded first - in that case, just take it out of A and it should work the same.
a.js: require(['b'], function(b) {
Just like A did, B will automatically load all its dependencies before it executes anything. A simple principle is to only refer a dependency if it's actually directly referenced in the file (or defines necessary global variables)
There's a set of JS modules representing similar OOP Classes: think of e.g. different types of backend tasks (SendEmailTask, WriteToDbTask, WriteToDiskTask), or different actions on a drawing canvas (DrawArc, DrawLine, DrawBezier). Those are just examples.
Each of those is a single JS file, with its own define, and they're all located in a common directory. In a client module that depends on all of those, the dependency list and argument list have to include each one of those separately, e.g. something like:
define([
'tasks/sendEmailTask', 'tasks/writeToDbTask', 'tasks/writeToDiskTask', ...
], function (SendEmailTask, WriteToDbTask, WriteToDiskTask, ...) {
/* ... */
/* ... new SendEmailTask(); */
/* ... new WriteToDbTask(); */
/* ... new WriteToDiskTask(); */
});
and they both must be updated everytime a new module is added to the set, e.g. MakeCoffeeTask, which seems to me as a BadThing™.
Is there a way to avoid those last issues? I was thinking of a couple of possible ways, but I don't know how to make them work:
Create a kind of namespace module. Each of those sub-modules depends on the namespace one and adds its definition to it. But than if the client too depends only on the namespace, how do you ensure that client gets loaded after all sub-modules?
Express both dependencies and arguments with some kind of wildcard, like 'tasks/*' for dependency and < no idea > for arguments.
You can make a different module for each section. For example: 'tasks/main'
in the Task main you can include all the files you need. and in the task main, all the function of task will be assigned. and you call high level functions. Take look :
define(['tasks/main'], function(task){
task.add('Project Status meeting');
task.SendEmailNotification('tAll');
});
in the task/main.js :
define(['tasks/sendEmailTask', 'tasks/writeToDbTask', 'tasks/writeToDiskTask',], function(sendEmailTask, writeToDbTask, writeToDiskTask){
var task = {
add = function(taskObj){
// write your code using writeToDbTask, writeToDiskTask
},
SendEmailNotification = function(whom){
// write your code using sendEmailTask, writeToDbTask, writeToDiskTask
};
return task;
});
does it help you ?
I was not able to find any other solution. This is what I came up with in the meantime... it is just an improvement over current situation, but I don't think it solves the posed issues.
// in tasks/taskNamespace.js or in any client code
define (function(require) {
var _taskArray = [
require('tasks/sendEmailTask'),
require('tasks/writeToDbTask'),
require('tasks/writeToDiskTask'),
/* ... , */
];
var TaskNamespace = {};
_taskArray.forEach(function (taskClass) {
TaskNamespace[taskClass.name] = taskClass;
});
return TaskNamespace;
});
It takes advantage of RequireJS Sugar syntax and of JS Function.name coming new feature, proposed in ES6.
What's the end result? You still have to manually add each Class to a list, but it's only one list instead of two. WHOA