Variable is pushed, but it doesn't exist later - javascript

I have the following code:
const scenarioList = []
const randomScenario = () => {
return scenarioList[Math.floor(Math.random() * scenarioList.length--)]
}
class Scenario{
setBG(){
//screen.bg = this.bg
//screen.redraw()
}
write(text, buttons, callback){
//$('#gametext > span').html(`<span>${text}</span>`)
//input.setText(buttons)
//input.bindAll(callback)
}
constructor(imgsrc, text, actions, callback){
let img = new Image()
img.src = imgsrc
this.bg = img
this.text = text
this.actions = actions
this.callback = callback
scenarioList.push(this)
console.log(scenarioList)
}
}
I init the class the following (and this is in the global scope)
new Scenario('./bg/1.png', 'You look around and see a huge mountain, what do you do?',[
'Climb It!!',
'Walk around',
'Other Direction',
'Rest',
], [
() => {
alert('a')
},
() => {
alert('a')
},
() => {
alert('a')
},
() => {
alert('a')
},
])
And verify with console.log(scenarioList)
[Scenario]
So its appended, but when I later try to do a console.log() on the same variable it is the following:
[]
Code that causes it:
const startGame = () => {
alert('were here') // this executes at the correct time, but later then variable init.
let scn = randomScenario()
console.log(scenarioList)
scn.write()
scn.setBG()
}
I am not seeing why this would happen, anyone can give me a push in the right direction?

I've found the solution, this code actually removed the element from the array:
const randomScenario = () => {
return scenarioList[Math.floor(Math.random() * scenarioList.length--)]
}
instead I did this:
return scenarioList[Math.floor(Math.random() * scenarioList.length -1)]

Related

Add prototype of a fuction

I have some question about my node.js project.
What I'm trying to do is, add additional functionality to a function.
So, I added new functionality using prototype, but it failed.
Below is my current code.
[ someFeatures.js ]
const functionFoo = new Function()
const functionBar = new Function()
module.exports = { functionFoo, functionBar }
[ addFeatures.js ]
// Import fuction
const { functionFoo, functionBar } = require('./someFeatures.js')
// Add additional feature
functionFoo.prototype.addtionalFeatureA = foo => {
return someFunction(foo)
}
// Add additional feature
functionBar.prototype.addtionalFeatureB = foo => {
return someOtherFunction(foo)
}
module.exports = { functionFoo, functionBar }
[ Other files will use this feature ]
const { functionFoo } = require('./someFeatures.js')
const aaa = new functionFoo()
aaa.addtionalFeatureA('bbb')
The result is 'TypeError: Cannot read properties of undefined (reading 'prototype')'
Is there any solution to fix this issue? Thanks in advance!
change new Function
into empty function
let yourFunction = function () {}
and change this
function.prototype.additional = foo => { ... }
to this
function.prototype.additional = function (foo) {
...
}

Reload HTML elements with javascript not working

I get a list of items and use it to dynamically create an HTML list
_loadList(){
HttpUtils.get('http://myserver/list/users/')
.then((res) => {
const self = this;
res.forEach((item) => {
userListContainer.append('<li> item.name </li>')
});
});
}
I call this function in the constructor, everything is working fine
constructor() {
this._loadList();
}
I am trying to recall this function every 5 seconds to update the list with the new result:
constructor() {
const that = this;
this._loadList();
window.setInterval(function(){
that._loadList();
}, 5000);
}
The function is called, the received result contains the new content, but the HTML is not updated. Do you have an idea about the problem?
You can try below code that will work for in your case. You can checkout https://es6console.com/jgyxgm1f/ example which will alert random number (in your case it's equivalent of adding new data coming from API response).
_loadList = () => {
HttpUtils.get('http://myserver/list/users/')
.then((res) => {
userListContainer.empty();
res.forEach((item) => {
userListContainer.append('<li> item.name </li>')
});
});
}
constructor = () => {
this._loadList();
window.setInterval(() => {
this._loadList();
}, 5000);
}

How to pass data from one function to another function that is an argument of the first function

In the below example, when using getData();, is it possible to access the data contained in its object map within a new function – ie. useData(); – that is an argument of getData();?
const getData = (useData) => {
const myData = {
0: { title: 'Hello' },
1: { title: 'World!' }
};
Object.keys(myData).map((item) => {
useData();
});
}
getData(console.log(
/**
* Somehow access data represented by `myData` and `item`
* in above object map along the lines of `myData[item].title`
*/
));
Do you want to achieve something like that?
You can call useData with some arguments inside map function. You can't call some function like console.log as argument to getData function in this case.
const getData = useData => {
const myData = {
0: { title: "Hello" },
1: { title: "World!" },
};
Object.keys(myData).map(item => {
useData(myData[item]);
});
};
getData(console.log);
Yes, that is the default behaviour. But you need to pass a function(console.log) instead of a function invocation(console.log()) and invoke it only later.
const getData = (useData) => {
const myData = {
0: { title: 'Hello' },
1: { title: 'World!' }
};
Object.keys(myData).map((item) => {
useData.apply(console, [item]);
useData.apply(console, [ myData[item].title ]);
//or useData(myData[item].title)
});
}
getData(console.log);
getData(console.log('something'));
is same as:
let x = console.log('something');
getData(x);

How to add a function to Object's named property with correct context in javascript

I have a working piece of code as below:
let pageParams = {
data: { todos: [], desc: '' }
}
pageParams.onLoad = function () {
//I am trying to encapsulate this to a standalone function and
// make it generic, instead of hard coding the 'this.addTodo=XXX'
const evProducer = {
start: listener => {
//Here, I am adding a named property function
this.addTodo = ev => {
listener.next(ev.detail.value)
}
},
stop: ()=>{}
}
const input$ = xs.create(evProducer)
input$.compose(debounce(400)).subscribe({
next: val => console.log(val)
})
}
The code works and now I am going to do some refactor work, i.e. move the logic out of this onLoad function. So I move the logic to another module
let xsCreator = {}
xsCreator.fromEvent = function(handler){
const evProducer = {
start: listener => {
handler = ev => listener.next(ev.detail.value)
},
stop: () => {}
}
return xs.create(evProducer)
}
And in the previous onLoad function becomes the following:
pageParams.onLoad = function () {
xs.fromEvent(this.addTodo).subscribe(blablabla)
}
but it does not work. I guess I might use apply/call/bind to make this work, but don't know how to. Anyone can help? Thanks in advance
I've found the solution, I should use Object.defineProperty to add a named property for object.
xsCreator.fromInputEvent = (srcObj, propertyName) => {
const evProducer = {
start: (listener) => {
Object.defineProperty(
srcObj,
propertyName,
{value: ev => listener.next(ev.detail.value)})
},
stop: () => {}
}
return xs.create(evProducer)
}

Rx timer state not updating in view in Cycle.js

I'm starting a timer when someone clicks a button that I intend to use as the opacity for some element. When I use do to trace the value I can see it spitting out to the console 40 times, but in the view the number stays put. Not sure where I'm going wrong here:
let intent = ({ DOM }) => ({
clickLogin$: DOM.select('.sign-in').events('click').map(ev => true)
})
let model = ({ clickLogin$ }) =>
Rx.Observable.combineLatest(
clickLogin$.startWith(false),
clickLogin$.map(x =>
Rx.Observable.timer(1, 1)
).switch().startWith(0).take(40),
(signingIn, fadeValue) => ({ signingIn, fadeValue })
)
let view = (state$) => {
return state$.do(
x => console.log(x.fadeValue)) // this fires |--1-2-3-4-5-6-7-8-->
.map(({ signingIn, fadeValue }) =>
div(`.app`, [
div([fadeValue]), // this value does not change
If(signingIn,
div(`.overlay`, {
style: {
backgroundColor: `rgba(0, 0, 0, 0.${fadeValue})` // nor does this
}
})
)
])
)
}
let main = (sources) => {
let view$ = view(model(intent(sources)))
return {
DOM: view$,
history: sources.History,
Props: sources.Props,
}
}
UPDATE: Turns out having a small error in hyperscript caused it strange behaviour. I didn't even include it in my example because I didn't think it was relevant.
div(`content`, [ `testing` ])
Simply changing the above to (adding indication of class)
div(`.content`, [ `testing` ])
Caused everything to magically work.
This is probably not a full answer, but it helps identifying the problem. I removed the If part of the view code generation, and added repeat, put that in tricycle and you can see that the fadeValue is generated sequentially as expected.
var Cycle = require('#cycle/core');
var CycleDOM = require('#cycle/dom');
var Rx = require('rx');
var makeDOMDriver = CycleDOM.makeDOMDriver;
var div = CycleDOM.div;
var sources = {
DOM: makeDOMDriver('.app')
};
let main = (sources) => {
let intent = ({ DOM }) => ({
clickLogin$: Rx.Observable.interval(3000).take(5).share()
})
let model = ({ clickLogin$ }) =>
Rx.Observable.combineLatest(
clickLogin$.startWith(false),
clickLogin$.flatMapLatest(function (x) {
return Rx.Observable.timer(200, 200);
}).take(10).repeat(),
(signingIn, fadeValue) => ({ signingIn, fadeValue })
)
let view = (state$) => {
return state$.do(
x => console.log(x.fadeValue)) // this fires |--1-2-3-4-5-6-7-8-->
.map(({ signingIn, fadeValue }) =>
div(`.app`, [
div([fadeValue]) // this value does not change
])
)
}
let view$ = view(model(intent(sources)))
return {
DOM: view$,
history: sources.History,
Props: sources.Props,
}
}

Categories