load different module on preferences - javascript

I would like to process an array of image files. When selecting them I can choose between selecting them randomly or one by one (queue). The decision is hold by the config.json.
First I initialize the processor and select the right image selection module by calling processImages and pass in the array of image files.
function processImages(images) {
const imageSelector = getImageSelector();
imageSelector.init(images); // initialize the module
console.log(imageSelector.getImage()); // test
}
function getImageSelector() {
const { random } = config;
const selector = random ? 'randomSelector' : 'queueSelector';
return require(`./imageSelectors/${selector}.js`);
}
The modules itself have their own logic to return the next image. For the random module I go for
let images;
module.exports = {
init: images => {
init(images);
},
getImage: () => {
return getImage();
}
};
function init(images) {
this.images = images;
}
function getImage() {
const index = getRandomIndex();
return images[index];
}
function getRandomIndex() {
const indexValue = Math.random() * images.length;
const roundedIndex = Math.floor(indexValue);
return images[roundedIndex];
}
and for the queue module I go for
let images;
let currentImageCounter = 0;
module.exports = {
init: images => {
init(images);
},
getImage: () => {
return getImage();
}
};
function init(images) {
this.images = images;
currentImageCounter = 0;
}
function getImage() {
const index = getNextIndex();
return images[index];
}
function getNextIndex() {
if (currentImageCounter > images.length)
currentImageCounter = 0;
else
currentImageCounter++;
return currentImageCounter;
}
When I run the code and random is true I get this error
C:...\imageSelectors\randomSelector.js:22
const indexValue = Math.random() * images.length;
TypeError: Cannot read property 'length' of undefined
When calling imageSelector.init(images) some image items are available so they just are undefined within the modules.
I think I missunderstood how to work with modules correctly. Could someone tell me how to setup the code correctly?

In your module, you declare a local variable images and use it as an object field this.images which is not right. Try this approach and do not shadow the upper-level variables with deeper-level variables with the same names to not be misled (i.e. use images as outer variable and something like imgs as function parameters). I've also a bit simplified your module code to avoid some unneeded duplication.
let images;
module.exports = {
init(imgs) {
images = imgs;
},
getImage() {
const index = getRandomIndex();
return images[index];
}
};
function getRandomIndex() {
const indexValue = Math.random() * images.length;
const roundedIndex = Math.floor(indexValue);
return images[roundedIndex];
}

Related

How do I get Data from Algolia searchClient to function in JavaScript?

I have a problem to get data from variables inside an inner Javascript function to the outer function.
What I am trying to do is to search Algolia-hits from a special category to show the first hit that has an image. So I can use this image for an category-overview. All works fine, except that i dont manage to get the img-Url from the hits.
My function looks like:
methods: {
getCategoryPicture(categoryName) {
const index = this.searchClient.initIndex("Testindex");
var FacetFilterString = "Kategorie: " + categoryName;
var imgUrl = "";
// search for hits of category
index
.search("", {
facetFilters: [FacetFilterString],
attributesToRetrieve: ["img", "Marke"],
hitsPerPage: 50
})
.then(({ hits }) => {
// search for first hit with img
var img = ""
hits.forEach((element) => {
if (element["img"] != undefined)
{
img = "www.someurl.com/" + element["img"];
console.log(img);
return img
}
});
this.imgUrl = img
return img;
});
return imgUrl;
},
},
The function finds the url, I can log it, but I dont manage to get it from the inner ".then"-function to the outer function. I cant reach the variables of the outer-function. "this" doesnt work eather. (because it points to the module, not to the outer function, i guess?).
I just want to return the first img-url the function finds.
Edit: I updated the Code, so it might be more clear. The function "setImgUrl" logs the picture perfectly, but it does not update the outer variable "imgUrl".
methods: {
getCategoryPicture(categoryName) {
const index = this.searchClient.initIndex("Testindex");
var FacetFilterString = "Kategorie: " + categoryName;
var imgUrl = "";
index
.search("", {
facetFilters: [FacetFilterString],
attributesToRetrieve: ["img", "Marke"],
hitsPerPage: 50
})
.then(({ hits }) => {
var img = ""
hits.forEach((element) => {
if (element["img"] != undefined)
{
img = "www.someurl.com/" + element["img"];
setImgUrl(img);
}
});
return img
});
function setImgUrl(img) {
imgUrl = img;
console.log(img);
}
return imgUrl;
},
},

Node.js: Exported function "is not a function" in one js file, but not another

So one of my files has a function that I need two of my other files to access. I am exporting this function with module.exports = {}. For some reason, one of my files is able to call this function, while I get a commands.commandRouter is not a function error when trying to call it from the other file. Here's basically what I've got going on:
commands.js
function commandRouter(commandName, commandType) {
if (commandType == 'sound') {
console.log(`${commandName} is a sound command, executing sound function`)
playAudio.playAudio(commandName.substring(1));
}
}
module.exports = {commandRouter}
main.js
const commands = require('./modules/commands.js');
const secondary = require('./modules/secondary.js');
client.on('message', (channel, tags, message, self) => {
if(message.charAt(0) == '!'){
console.log('Trigger character identified');
if(commands.commandList.hasOwnProperty(message.toLowerCase())) {
console.log('Valid command identified')
if (commands.commandList[`${message}`] == 'random' ) {
console.log('Random-type command identified')
secondary.randomSelectPropery(message.toLowerCase().substring(1));
}
else
{
console.log('Regular command identified')
commands.commandRouter(message, commands.commandList[`${message}`]);
}
}
}
}
commands.commandRouter(paramA, paramB); works just fine in this instance
secondary.js
const commands = require('./commands.js');
var randomSelectPropery = function (commandObject) {
randomObject = eval(commandObject);
var keys = Object.keys(randomObject);
console.log(randomObject)
console.log(`This object has ${keys.length} commands to choose from`);
var newCommandName = Object.getOwnPropertyNames(randomObject)[keys.length * Math.random() << 0];
console.log(newCommandName)
var newCommandType = randomObject[`${newCommandName}`]
console.log(newCommandType);
commands.commandRouter(newCommandName, newCommandType);
};
const perfect = {
"!perfectqube": "sound",
"!perfectsf2": "sound",
};
module.exports = { perfect, randomSelectPropery }
Here, commands.commandRouter(paramA, paramB); give the commands.commandRouter is not a function error.
File structure is as follows:
.\folder\main.js
.\folder\modules\commands.js
.\folder\modules\secondary.js

How to get utility function from helper file on node.js server?

I have a node/express server and I'm trying to get a function from a helper file to my app.js for use. Here is the function in the helper file:
CC.CURRENT.unpack = function(value)
{
var valuesArray = value.split("~");
var valuesArrayLenght = valuesArray.length;
var mask = valuesArray[valuesArrayLenght-1];
var maskInt = parseInt(mask,16);
var unpackedCurrent = {};
var currentField = 0;
for(var property in this.FIELDS)
{
if(this.FIELDS[property] === 0)
{
unpackedCurrent[property] = valuesArray[currentField];
currentField++;
}
else if(maskInt&this.FIELDS[property])
{
//i know this is a hack, for cccagg, future code please don't hate me:(, i did this to avoid
//subscribing to trades as well in order to show the last market
if(property === 'LASTMARKET'){
unpackedCurrent[property] = valuesArray[currentField];
}else{
unpackedCurrent[property] = parseFloat(valuesArray[currentField]);
}
currentField++;
}
}
return unpackedCurrent;
};
At the bottom of that helper file I did a module.export (The helper file is 400 lines long and I don't want to export every function in it):
module.exports = {
unpackMessage: function(value) {
CCC.CURRENT.unpack(value);
}
}
Then in my app.js I called
var helperUtil = require('./helpers/ccc-streamer-utilities.js');
and finally, I called that function in app.js and console.log it:
res = helperUtil.unpackMessage(message);
console.log(res);
The problem is that the console.log gives off an undefined every time, but in this example: https://github.com/cryptoqween/cryptoqween.github.io/tree/master/streamer/current (which is not node.js) it works perfectly. So I think I am importing wrong. All I want to do is use that utility function in my app.js
The unPackMessage(val) call doesn't return anything:
module.exports = {
unpackMessage: function(value) {
CCC.CURRENT.unpack(value);
}
}
you need to return CCC.CURRENT.UNPACK(value);
module.exports = {
unpackMessage: function(value) {
return CCC.CURRENT.unpack(value);
}
}

Node.js classes as modules

I am trying to make my application more object orientated. for this i want to create the following class (object):
in the file Media.js
//Media object
var Media = function (file, targetDirectory) {
this.file = file;
this.targetDir = targetDirectory;
this.fileName = this.getName();
};
Media.prototype.isVideo = function () {
return this.file.mimetype.indexOf('video') >= 0;
};
Media.prototype.isAudio = function () {
return this.file.mimetype.indexOf('audio') >= 0;
};
Media.prototype.getName = function () {
return this.file.originalname.substr(0, this.file.originalname.indexOf('.'))
};
I wish to use this object in serveral places of my application however im not quite sure how to include it. Also is this a good idea or should i use Modules instead?
You can export your Media object as follows in Media.js
module.exports = Media;
then simply require Media.js when you need it
const Media = require('pathtofile/Media.js')
Media.isAudio(a, b);

Create a pipeline from Json to streams with transducers-js and most.js

I have this Amd module
define(function (require, exports, module) {
'use strict';
var t = require("transducers");
var most = require("most");
var groupby = function (prev, curr) {
var key = curr.type;
if (!prev[key]) {
prev[key] = [curr];
} else {
prev[key].push(curr);
}
return prev;
};
function category(kv) {
return {
type: kv[0],
label: kv[1][0].label,
counter: kv[1].length
}
}
function dom(cat) {
var el = document.createElement("li");
el.innerHTML = cat.label;
return el;
}
function append(prev, curr) {
prev.appendChild(curr);
return prev;
}
function createClick(prev, curr) {
return prev.merge(most.fromEvent("click", curr)
.map(function (e) {
return e.currentTarget.innerHTML;
})
)
}
var xf = t.comp(
t.map(category),
t.map(dom)
);
module.exports = {
main: function (data) {
var groups = t.reduce(groupby, {}, data);
var container = t.transduce(xf, append, document.querySelector("ul"), groups);
var streams = t.reduce(createClick, most.empty(), [].slice.call(container.querySelectorAll("li"), 0));
streams.forEach(function (e) {
console.log("click", e);
});
}
};
});
Main function takes a list of items, then groups them by 'type' property. After that it creates and appends < li > elements. Finally it creates a stream of clicks. I'm new in reactive programming and transducers.
But I was wondering if there would be a way to create a pipeline.
I trouble because groupby is a reduction and a can't compose it in transducer. I'm sure I'm missing something. Thanks
Try and separate your problem into things that can operate on the individual item vs on the collection and wait until last to reduce them. also check into the often missed "scan" operation which can save you from over aggressive reductions
In your example, you have 3 reducing possible operations listed:
- merge all click streams into one stream of events
- merge all dom into a single ul
- count
the can all be accomplished with scan, but the issue arrises in that you want to unique categories, but you also count the non unique ones. It's not clear from your example if that's actually a requirement though...
Since most already works similar to transducers, you don't really need them. For this example I'll stick with pure mostjs;
var most = require("most");
function gel(tag) {
return document.createElement(tag);
}
var cache = Object.create(null);
function main(dataArray) {
most.from(dataArray)
//only pass along unique items to represent categories
//optionally, also count...
.filter(function uniq(item) {
var category = item.type;
if (!(category in cache))
cache[category] = 0;
cache[category]++;
return cache[category] == 1;
})
//transform
.map(function makeLI(item) {
var li = gel("li");
li.innerHTML = item.label;
item.dom = li;
})
//attach click handler
.map(function (item) {
item.click = most
.fromEvent("click", item.dom)
.map(function(e) {
item.label;
});
return item;
})
// merge
.scan(function mergeIn(all, item) {
el.appendChild(item.dom);
clicks.merge(item.click);
}, { ul: gel("ul"), clicks: most.empty() })
//force stream init b creating a demand
.drain()
//most resolve stream into promises, but we could have just
//as easily used reduce here instead
.then(function onComplete(all) {
all.clicks.forEach(function(msg) {
console.log("click", e);
})
})
}
further variation are possible. for example if we wanted to add a sublist for each category item, we could attach a stream to the context object for each category and incrementally append to each child as we go

Categories

Resources