jQuery.when() need to be cleared up - javascript

I have a simple .html page like this :
</html>
<head>
<script type="text/javascript" src="jquery/jquery-1.8.2.js"></script>
...
<script type="text/javascript">
var obj;
function document_load() {
obj = new mySpace.myClass();
console.log("end document load");
}
</script>
</head>
<body onload="document_load()">
...
...
</body>
</html>
myClass is a TypeScript class with this constructor :
public constructor() {
console.log("begin constructor");
(<any>$).when(
jQuery.getJSON('path/myJson1.json', function (data) {
this.obj1 = data;
console.log("here1");
}),
jQuery.getJSON('path/myJson2.json', function (data) {
this.obj2 = data;
console.log("here2");
})
).then(function () {
if (this.obj1 && this.obj2) {
console.log("here3");
this.obj3 = new myClass3();
this.obj4 = new myClass4();
console.log("everything went ok");
}
});
}
Actually the console prints this :
begin constructor
end document load
here1
here2
The reason of this behaviour is (of course) cause of asynchronous jQuery calls (or at least I guess). How can I obtain the following behaviour?
begin constructor
here1
here2
here3
everything went ok
end document load
I clarify that the jsons are taken correctly (I tried to print them and they are correct).

That's because you're not returning a promise to jQuery.when, so the callback gets called and this.obj1 && this.obj2 are both null.
A better way to do this would be:
(<any>$).when(
jQuery.getJSON('path/myJson1.json'),
jQuery.getJSON('path/myJson2.json')
)
.then(function (obj1, obj2) {
// Code
});

Replace all functions with arrow functions (=>). This will ensure that "this" points to the correct thing in all function bodies.
More : https://www.youtube.com/watch?v=tvocUcbCupA

Related

how to call js method that exist in 2 js files?

To my html file i add 2 js files
<head>
<script type="text/javascript" src="js_001.js"> </script>
<script type="text/javascript" src="js_002.js"></script>
</head>
both those js files contain method call 'func1'
How i call func1 from js_002 ?
If there is method func1 => js_001
and method func2 => js_002
When i call the func2 from my html code - i get an error about that func2 does not exist on js_001 ... why is that and how to fix it ?
Functions defined with the same name in the global scope will overwite themselves. Last definition will overwite the previous one.
So you could populate your functions inside other scopes, for example, objects:
// In js_001.js
var js_001 = {
foo : function() {
}
};
// Inside js_002.js
var js_002 = {
foo : function() {
}
};
Then you can invoke both functions by: js_001.foo(); and js_002.foo();.
Hope it helps.
As others said you can't. That is why for example using modules is a good idea when you have larger applications.
You could write your scripts in your functions in the js files inside a module that includes all functions related to some functionality like this
File js_001.js
var js_001 = (function () {
return {
foo : function () {
// code
}
};
})();
File js_002.js
var js_002 = (function () {
return {
foo : function () {
// code
}
};
})();
And call your functions like this:
onclick="js_001.foo()"
onclick="js_002.foo()"

Jquery execute two functions on click

I am trying to execute functions on click, Below is click button on HTML,
Insights.init() will execute on page load will give me some data from server, now with click on button, i need to pass variable to month function to filter data, and with click i want to execute all functions inside Insights()
var Insights = function() {
var initCheckColor = function(vari) {
console.log(vari);
}
var testFunction = function(vari) {
console.log('test');
}
return {
init: function() {
initCheckColor();
testFunction();
}
};
}();
jQuery(document).ready(function() {
Insights.init();
});
function month(vari) {
console.log("hoo");
return {
init: function() {
initCheckColor(vari);
testFunction();
}
};
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Month
Now problem is, i can see "hoo" printed on console when i click on link, but i also want to print it with execution of initCheckColor(vari) function, means i want output two times, but i could not output it,
How can i get output two times?
Problem: Is with this code
function month(vari) {
console.log("hoo");
//this block of code
return {
init: function() {
initCheckColor(vari);
testFunction();
}
};
// upto here
}
When you call the month function you are returning a object with a property named init Note: you are just returning a object and not executing the functions within the property. Also other issue is this property is a function which executes two other function, But those functions are not available in the current scope. As they are equal to Private methods for the Insights object.
Solution: Would be to re initialize the object with data just like how you are doing on page load.
I have fixed your code and added comments in the code where the changes were made.
var Insights = function() {
var initCheckColor = function(vari) {
console.log(vari);
}
var testFunction = function(vari) {
console.log('test');
}
return {
init: function(vari) { // have a input parameter during initialization.
initCheckColor(vari);
testFunction();
}
};
}();
jQuery(document).ready(function() {
Insights.init('something'); // I pass in the string "something" now this will be printed by the initCheckColor function.
});
function month(vari) {
console.log("hoo");
Insights.init(vari); // initialize the Insights object by passing in some value.
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Month

Javascript callback within class loses binding

I have a problem with my class where I set a callback function to fire after an ajax request, this works fine except for the callback then having this= window instead of this = the calling class. I have tried fiddling with the bindings etc to no avail. any help appreciated.
<?php
if (isset($_POST['id'])){
echo json_encode(array('key' => 'val'));
die;
}
?>
<script type="text/javascript" src="/linkup/js/mootools-core-1.4.3-full-compat-yc.js" charset="utf-8"></script>
<script type="text/javascript" src="/linkup/js/mootools-more-1.4.0.1.js" charset="utf-8"></script><script>
var myClass = new Class({
blah: function(){
console.log('this worked ok');
},
foo: function(){
this.blah(); // at this point it is failing with "unknown function"
},
bar: function(){
this.reqJSON({id:1,req:'grabpoints'},this.foo);
},
// data - an aray containing some data to post {id:1,req:'grabpoints'}
// onS - a function to fire on return of data
reqJSON: function(data,onS){
if (this.jsonRequest) this.jsonRequest.cancel();
this.jsonRequest = new Request.JSON({
url: 'test.php',
onRequest: function (object){
console.log('sending json');
},
onSuccess: function (object){
console.log('json success');
onS(object);
}
}
).post(data);
},
});
var o = new myClass();
o.bar();
this is never part of an inherited scope (i.e. the closure) for a function, but instead determined when the function is called, in this case by onS(object). Called this way, the function is just that - a function. You need to call this.onS(object), but this won't work in your case because the onSuccess function does not know about this either.
To call the foo/onS function with the outermost object as this you must save a reference to it in another variable, commonly called that:
reqJSON: function(data,onS){
var that = this;
...
onSuccess: function (object){
console.log('json success');
that.onS(object);
}
change this
bar: function(){
this.reqJSON({id:1,req:'grabpoints'},this.foo);
}
to :
bar: function(){
var self = this;
this.reqJSON({id:1,req:'grabpoints'},self.foo);
}

Javascript: Extend a Function

The main reason why I want it is that I want to extend my initialize function.
Something like this:
// main.js
window.onload = init();
function init(){
doSomething();
}
// extend.js
function extends init(){
doSomethingHereToo();
}
So I want to extend a function like I extend a class in PHP.
And I would like to extend it from other files too, so for example I have the original init function in main.js and the extended function in extended.js.
With a wider view of what you're actually trying to do and the context in which you're doing it, I'm sure we could give you a better answer than the literal answer to your question.
But here's a literal answer:
If you're assigning these functions to some property somewhere, you can wrap the original function and put your replacement on the property instead:
// Original code in main.js
var theProperty = init;
function init(){
doSomething();
}
// Extending it by replacing and wrapping, in extended.js
theProperty = (function(old) {
function extendsInit() {
old();
doSomething();
}
return extendsInit;
})(theProperty);
If your functions aren't already on an object, you'd probably want to put them there to facilitate the above. For instance:
// In main.js
var MyLibrary = {
init: function init() {
}
};
// In extended.js
(function() {
var oldInit = MyLibrary.init;
MyLibrary.init = extendedInit;
function extendedInit() {
oldInit.call(MyLibrary); // Use #call in case `init` uses `this`
doSomething();
}
})();
But there are better ways to do that. Like for instance, providing a means of registering init functions.
// In main.js
var MyLibrary = (function() {
var initFunctions = [];
return {
init: function init() {
var fns = initFunctions;
initFunctions = undefined;
for (var index = 0; index < fns.length; ++index) {
try { fns[index](); } catch (e) { }
}
},
addInitFunction: function addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
}
}
};
})();
Here in 2020 (or really any time after ~2016), that can be written a bit more compactly:
// In main.js
const MyLibrary = (() => {
let initFunctions = [];
return {
init() {
const fns = initFunctions;
initFunctions = undefined;
for (const fn of fns) {
try { fn(); } catch (e) { }
}
},
addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
// Or: `Promise.resolve().then(() => fn());`
// (Not `.then(fn)` just to avoid passing it an argument)
}
}
};
})();
There are several ways to go about this, it depends what your purpose is, if you just want to execute the function as well and in the same context, you can use .apply():
function init(){
doSomething();
}
function myFunc(){
init.apply(this, arguments);
doSomethingHereToo();
}
If you want to replace it with a newer init, it'd look like this:
function init(){
doSomething();
}
//anytime later
var old_init = init;
init = function() {
old_init.apply(this, arguments);
doSomethingHereToo();
};
The other methods are great but they don't preserve any prototype functions attached to init. To get around that you can do the following (inspired by the post from Nick Craver).
(function () {
var old_prototype = init.prototype;
var old_init = init;
init = function () {
old_init.apply(this, arguments);
// Do something extra
};
init.prototype = old_prototype;
}) ();
Another option could be:
var initial = function() {
console.log( 'initial function!' );
}
var iWantToExecuteThisOneToo = function () {
console.log( 'the other function that i wanted to execute!' );
}
function extendFunction( oldOne, newOne ) {
return (function() {
oldOne();
newOne();
})();
}
var extendedFunction = extendFunction( initial, iWantToExecuteThisOneToo );
2017+ solution
The idea of function extensions comes from functional paradigm, which is natively supported since ES6:
function init(){
doSomething();
}
// extend.js
init = (f => u => { f(u)
doSomethingHereToo();
})(init);
init();
As per #TJCrowder's concern about stack dump, the browsers handle the situation much better today. If you save this code into test.html and run it, you get
test.html:3 Uncaught ReferenceError: doSomething is not defined
at init (test.html:3)
at test.html:8
at test.html:12
Line 12: the init call, Line 8: the init extension, Line 3: the undefined doSomething() call.
Note: Much respect to veteran T.J. Crowder, who kindly answered my question many years ago, when I was a newbie. After the years, I still remember the respectfull attitude and I try to follow the good example.
This is very simple and straight forward. Look at the code. Try to grasp the basic concept behind javascript extension.
First let us extend javascript function.
function Base(props) {
const _props = props
this.getProps = () => _props
// We can make method private by not binding it to this object.
// Hence it is not exposed when we return this.
const privateMethod = () => "do internal stuff"
return this
}
You can extend this function by creating child function in following way
function Child(props) {
const parent = Base(props)
this.getMessage = () => `Message is ${parent.getProps()}`;
// You can remove the line below to extend as in private inheritance,
// not exposing parent function properties and method.
this.prototype = parent
return this
}
Now you can use Child function as follows,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
We can also create Javascript Function by extending Javascript classes, like this.
class BaseClass {
constructor(props) {
this.props = props
// You can remove the line below to make getProps method private.
// As it will not be binded to this, but let it be
this.getProps = this.getProps.bind(this)
}
getProps() {
return this.props
}
}
Let us extend this class with Child function like this,
function Child(props) {
let parent = new BaseClass(props)
const getMessage = () => `Message is ${parent.getProps()}`;
return { ...parent, getMessage} // I have used spread operator.
}
Again you can use Child function as follows to get similar result,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
Javascript is very easy language. We can do almost anything. Happy JavaScripting... Hope I was able to give you an idea to use in your case.
as I understand it, you are trying to fetch the applications connected to the user account. You can do this by making a request on the API, I don't know if discord.js covers this part of the API
endpoint: https://discord.com/api/users/#me/connections
Request type: GET Header:
Authorization: "Beareryou token"
response: [
{...}
]
Use extendFunction.js
init = extendFunction(init, function(args) {
doSomethingHereToo();
});
But in your specific case, it's easier to extend the global onload function:
extendFunction('onload', function(args) {
doSomethingHereToo();
});
I actually really like your question, it's making me think about different use cases.
For javascript events, you really want to add and remove handlers - but for extendFunction, how could you later remove functionality? I could easily add a .revert method to extended functions, so init = init.revert() would return the original function. Obviously this could lead to some pretty bad code, but perhaps it lets you get something done without touching a foreign part of the codebase.

Javascript: return function with predefined arguments

I have a function like
function a (p1, p2) { /* ... */ }
and in some scope want to get something like this:
function b (/* no params! */) { return a (my1, my2) }
where my1 and my2 are defined somehow in this scope. So I should get a parameterless function b, which when called calls a with fixed parameters my1 and my2. Now, the question is, why this is not right, and which is :)
UPD: Ok, I had some callbacks in those params, now found out, how to process them all. What I missed was to apply the technique twice. Thank you.
Just make a function that returns a new function b:
function getB(my1, my2) {
return function() {
a(my1, my2);
}
}
and use it like this:
var b = getB(my1, my2);
Write a function that takes my1 and my2 and creates function b:
function make_b(my1, my2){
return function b(){ return a(my1, my2);};
}
I'm not sure if I understood you correctly, but you can look at a concept called currying. It is possible to curry a function in Javascript such that you can obtain another function with some or all of the parameters preset.
You can look at an implementation here.
If you are using Prototype, you can obtain the function b this way.
var b = a.curry(arg1, arg2);
now calling b() is the same as calling a(arg1, arg2)
Why is this not right? Are you getting an error? I tried to reproduce a working sample based one your description and what I have works so perhaps you could post a more detailed sample:
<script>
function a(p1, p2)
{
return 'hello ' + p1 + ' and ' + p2;
}
function b(my1,my2)
{
return function()
{
return a(my1,my2);
}
}
var wrapper=b();
alert(wrapper());
</script>
Edit
Based on your comment to another answer I updated my sample to show how you can wrap a function.
Edit 2
Ok so I replaced them with variables;-)
Put the values in an array (or JSON) and return the array.
function a (p1,p2) {
var my = []
my[0] = p1
my[1] = p2
return my
}
function b () {
return a(my1,nmy2)
}
Maybe I'm missing the point in your example, I don't know.
There appear to be three parts:
Defining a:
function a(M, N) {
return M + N;
}
Defining b:
var X = 10;
var Y = 25;
var b = function() {
return a(X, Y);
}
Using b:
var thirtyFive = b(); // thirtyFive = 35
This example uses the assignment of an onclick event handler
during page load to demonstrate how to create a function
reference containing embedded references to then local
values in the setup function.
<html>
<head>
<title>Scope passing Test</title>
<script type="text/javascript">
// Your target function
function a(p1,p2) { alert("p1="+p1+ " p2="+p2); }
function yourSetupFunction()
{
// Declare some local variables that your "a()" function cannot see to test.
var my1 ="Look Ma" ;
var my2 ="No hands" ;
// Snag a reference to the <a id="testA"></a> element
var oAelement=document.getElementById("testA");
oAelement.addEventListener( "click" ,
(function(scopePass_My1,scopePass_My2)
{
return function()
{
a(scopePass_My1,scopePass_My2)
}
})(my1,my2) ,true);
}
</script>
</head>
<body onload="yourSetupFunction()">
<a id="testA" href="#" onclick="return false;">Click to Test</a>
</body>
</html>
The actual magic is just a few lines
(function(scopePass_My1,scopePass_My2)
{
return function()
{
a(scopePass_My1,scopePass_My2)
}
})(my1,my2)
The first set of parens cause the contents to be evaluated to a function reference.
The second set of parens ... (my1,my2) ... cause the function reference to be called
which returns another function reference which can see the parameters passed in
... scopePass_My1,scopePass_My2 ... and is able to pass these to your target function a(p1,p2)
Hope that helps.

Categories

Resources