How to override javascript method and call from class? - javascript

Excuse the title but I'm not really sure what this is called (Maybe events?):
I have created a class that someone will use:
function cls_something()
{
this.notify('hello');
}
Now the person using my class creates a method called 'notify' (as instructed by me) in order to listen for notifications and then perform their own custom code using the param I pass:
var something = new cls_something();
something.notify = function(message)
{
console.log('The notification is ' + message);
}
How do I call this method from within the class to give him the notification message?
Fiddle
I'm trying to achieve something like this...
websocket = new WebSocket("ws://localhost:10000");
websocket.onopen = function(e)
{
console.log('you are connected');
}
websocket.onmessage = function(e)
{
console.log('omg wtf ffs, there was an error: ' + e.msg);
}

You can just call this.notify("Message"); You'd probably want to check to see if it's defined first, though.
EDIT 1:
Ok, so your problem here is that you're calling a function straight from the constructor, before it's defined. If it needs to be defined in the constructor, then pass the function as a parameter.
function cls_something(notifyFunction)
{
notifyFunction('hello');
}
EDIT 2:
Just so we're clear, you can have the user of your class define functions later, if you'd like. You just can't run them straight from the constructor, obviously. If you run them from the constructor, they need to be defined before hand.
Say your class was something like
function cls_something()
{
this.someFunctionThatIsRunLater = function() {
this.notify('hello');
}
}
Then your client can write
var something = new cls_something();
something.notify = function(message)
{
console.log('The notification is ' + message);
}
Then, when the client calls
something.someFunctionThatIsRunLater();
Notify will be called.

Related

Unable to set variable in a function calling it from another function

I'm currently running a node js file and I'm receiving a post like so.
app.post('/', function (req, res) {
var firstLine = req.body.firstLine;
var secondLine = req.body.secondLine;
var previewID = req.body.previewId;
takeWebshot(firstLine)
return res.end('<h1>Hello, Secure City World!</h1>');
});
when I console.log firstLine it's set to the req.body.firstLine let us say it's "Hello". So firstLine = "Hello".
I then pass this variable to takeWebshot(firstLine).
When I console log fLine in takeWebshot I can see "Hello".
function takeWebshot(fLine) {
console.log(fLine);
var options = {
onLoadFinished: {
fn: function() {
document.getElementById("user_input").value=fLine;
document.getElementById("second_user_input").value="AMAZON USERNAME";
document.getElementById("preview_btn").click();
}
},
takeShotOnCallback: true,
captureSelector: '.fancybox-outer'
};
webshot('example.com/testy.html', './example.png', options, function(err) {
if (err) return console.log(err);
console.log('OK');
});
};
Here is my problem in this line:
document.getElementById("user_input").value=fLine;
fLine is not read anymore. I tried passing fLine into the function here like so fn: function(fLine). fLine now equals "success". In my limited knowledge of JS it appears that the function fn: function() is a promise callback in the main node-module webshot. The goal is I need
document.getElementById("user_input").value=fLine; to equal firstLine that is being sent by the other function.
EDIT: webshot is calling a phantom js to open a url headless. I'm trying to pass the variable so it can fill out a form when it calls it to take a screen shot. That is why it has document.
The documentation for webshot mentions that the script will get serialised before being passed to Phantom
Note that the script will be serialized and then passed to Phantom as text, so all variable scope information will be lost. However, variables from the caller can be passed into the script as follows:
Cf https://www.npmjs.com/package/webshot#phantom-callbacks
So you should probably follow their instructions and have something like this:
onLoadFinished: {
fn: function() {
document.getElementById("user_input").value=this.fLineSnapshot;
document.getElementById("second_user_input").value="AMAZON USERNAME";
document.getElementById("preview_btn").click();
},
context: {
fLineSnapshot: fLine
}
},
you cannot pass fLine into fn: function(fLine) since it is a callback function of onLoadFinished, the scope of the variable is not reachable inside, you can try fn: () => {
document.getElementById("user_input").value=fLine;
} this might work as fat arrow function with allow access to use variable outside function.

React Native function calls not working – can’t find `this.function2`

I cannot get this working. It might be simple but there is just no information online that works.
Here is what I am trying to do.
class Test {
componentDidMount() {
this.function1();
}
function1() {
var myListener = listener.on(something) {
console.log('function1 triggered');
key = 'djh3489739082';
name = 'gary';
email = 'gary#email.com';
this.function2(key, name, email);
}
}
function2 = ({ key, name, email }) => {
console.log('key: ' + key);
console.log('name: ' + name);
console.log('email: ' + email);
}
}
That's basically it. The error I get in the console is that it can't find variable this.function2.
It doesn't work when I try removing the this. prefix. I also have a much simpler function call in my code that works fine like this:
function3() {
// Some code here
this.function4();
}
function4() {
// Do some things.
}
And function3 calls function4 without issue. It's just because I need to pass parameters that it falls over and like NO ONE online needs to do this, apparently. The only examples I have found use const before the function. So like:
const function2 = ({ parameter1, parameter2, parameter3 }) => {
But this immediately throws an error. I can't use const or var or any of that stuff.
This should be easy, surely! Any ideas?
Here's what's wrong in your code. How many parameters does your function2 take? One, not three, but one. It takes a JSON object as a parameter, who has 3 properties: key, name and email, because you wrapped them with {}, but when you call it in function1, you passed 3 parameters to it, without the {}, which makes it not a JSON object.
So, you can either:
// Don't modify function2 but change function1 like so
function1() {
this.function2({ key, name, email })
}
or
// Don't modify function1 but change function2 like so
function2(key, name, email) {
}

WebOS 3.0 Access to UI from function

I cannot access to enyo Ui component from function:onComplete in WebOS 3.0.
buttonTapped: function(inSender, inEvent) {
console.log("Button is clicked");
this.$.txt.setContent(inSender.name + " tapped."); // This worked
var request = webOS.service.request("luna://com.webos.service.tv.systemproperty", {
method: "getSystemInfo",
parameters: {"keys": ["modelName", "firmwareVersion", "UHD", "sdkVersion"]},
onComplete: function (inResponse) {
var isSucceeded = inResponse.returnValue;
if (isSucceeded){
console.log("Result: " + JSON.stringify(inResponse));
$.txt.setContent("Result: "+JSON.stringify(inResponse)); // This is not worked
}
}
});
...
Console output
Button clicked
Result{"modelName":"WEBOS1","firmwareVersion":"03.00.00","UHD":"false","sdkVersion":"03.00.00","returnValue":true}
Uncaught TypeError: Cannot read property 'txt' of undefined
I not found any documentation about this.
The reason for the error is that your callback function is not executing in the context of your component. this is not your component (not to mention you're missing the keyword this in front of $.txt...).
What you need to do is bind the context of the callback function or use it to create a closure over a variable that contains a reference to this.
This is a such a common occurrence that Enyo provides a utility method for this: this.bindSafely.
Try the following:
onComplete: this.bindSafely(function (inResponse) {
var isSucceeded = inResponse.returnValue;
if (isSucceeded){
console.log("Result: " + JSON.stringify(inResponse));
this.$.txt.setContent("Result: "+JSON.stringify(inResponse));
}
})
See: http://enyojs.com/docs/latest/#/kind/enyo/CoreObject/Object:bindSafely

Call a function in node.js programming

I have the following code:
Manager.prototype.checkOrder = function() {
var finish = function(err, filled) {
if(!filled) {
log.info(this.action, 'order was not (fully) filled, cancelling and creating new order');
this.exchange.cancelOrder(this.order);
}
log.info(this.action, 'was successfull');
}
this.exchange.checkOrder(this.order, _.bind(finish, this));
}
And I don't know how to call it on other parts of the code.
I have tried this :
setTimeout(this.checkOrder, util.minToMs(1));
but it didn't work.
I want to do it without using setTimeout function.
As you are using prototypes you probably want to create an Object first. After that you can call the method like every other function.
var myManager = new Manager();
myManager.checkOrder();

Call a method after a callback and an event

I have a module with four functions that call one after the other. I am trying to follow the Revealing Module Pattern. One of the functions is public, the remaining are private. It goes like this:
publicMethod is called from another module
queryNames is called from publicMethod
execute(parameters, callback?, errback?) is called from queryNames
addNamesList is called as the callback? argument of execute
Several dijit/form/CheckBox's are created and the method querySegments is triggered onChange
querySegments needs to call a method of an object created in publicMethod.
The problem is in step 6, I can't reach the object created in step 1.
I have tried to use dojo hitch to define the callback? argument in step 3, but I can't get it to work. I tried putting this in its first argument, but even then I can't reach the required scope to call addNamesList.
Here is some code to demonstrate this issue.
define([
'dojo/dom',
'dijit/form/CheckBox',
'esri/layers/ArcGISDynamicMapServiceLayer',
'esri/tasks/query',
'esri/tasks/QueryTask',
'dojo/_base/lang'
],
function (
dom,
CheckBox,
ArcGISDynamicMapServiceLayer,
Query, QueryTask,
lang
) {
// ***************
// private methods
// ***************
// fetch names and call addNamesList to put the list in place
var queryNames = function (map, mapLayer) {
// new QueryTask(url, options?)
var queryTask = new QueryTask("url")
var query = new Query()
// execute(parameters, callback?, errback?)
// this callback passes an argument called featureSet
queryTask.execute(query, lang.hitch(map, "addNamesList", mapLayer), function(error) {console.log(error)})
}
// callback function of queryNames
var addNamesList = function (mapLayer, featureSet) {
console.log('addOplist')
var namesCount = featureSet.features.length
for (var i = 0; i <namesCount; i++) {
// work
var cbox = new CheckBox({
id: "cbox_" + i,
value: featureSet.features[i].attributes["someID"],
checked: false,
onChange: function (evt) {
querySegments(this.value, mapLayer)
}
})
cbox.placeAt("someDiv" + i, "first")
}
}
// triggered by the checkbox event
var querySegments = function (name, mapLayer) {
// build the query
var queryStatement = "someID = " + name
var layerDefinitions = [queryStatement]
// call a method of mapLayer
mapLayer.setLayerDefinitions(layerDefinitions)
}
// **************
// public methods
// **************
var publicMethod = function (map) {
var mapLayer = new ArcGISDynamicMapServiceLayer('restURL')
map.addLayer(mapServiceLayer)
queryNames(map, mapLayer)
return mapLayer
}
return {
publicMethod: publicMethod
}
}
)
You can see a more detailed explanation and a working example on this other (and more broad) question that I have put on Code Review.
I am new to JavaScript and I guess I still have a lot of issues with scoping, closures and callbacks.
I will deeply appreciate any input, including how to improve this question.
Edit
With this current implementation (with dojo hitch), no error is thrown. The method addNamesList is not called (nor errback, which I also don't understand why). I think this is because addNamesList is not on map's (hitch first argument) namespace. I tried to put this instead, but it makes no difference.
Before I decided to use hitch, the code looked like this:
var queryNames = function (map, mapLayer) {
...
queryTask.execute(query, addNamesList)
}
var addNamesList = function (featureSet) {
...
...
...
querySegments(this.value, mapLayer)
}
but then I couldn't reach mapLayer inside the method triggered by the check box event. It would throw Uncaught ReferenceError: mapLayer is not defined. That is why I tried to use hitch.
Javascript is asynchronous, so pretty much data coming from db, http requests or whatever is returned via callbacks. Here's what happens in your code:
public method calls queryNames
queryNames call addNamesList of map asynchronously and returns nothing
public method takes back control, meanwhile some stuff is going on with the addNamesList
mapLayer is returned untouched while some stuff is still going on in the background
So, to avoid this, you should return data from public method via callback, so you pass callback as the second parameter to the public method, then to the querySegments. Then, in the success callback of query, when you finally get the result ready, you do:
callback(mapLayer);
So, everything you should do is to pass this callback as deep as needed to the place where you have your mapLayer ready (so you've done with it everything you wanted), and then do a callback(mapLayer);.
This and this would probably explain better.
Best regards, Alexander

Categories