Perform action based on callback(true) / callback(false) - javascript

I want to be able to perform some logic within a callback function based on whether callback(true) or callback(false) was called in the preceeding function.
Example:
foo.doFunction = function (param, callback)
{
int a = 1;
int b = param;
if(a < param)
{
callback(false);
}
else
{
callback(true);
}
}
foo.doFunction(param, function()
{
if(true)
{
}
if(false)
{
}
});
Is what I am trying to achieve possible through the use of callbacks?
Thanks for your time.

Yes, though your callback function would need to read the argument by name or using the arguments array:
foo.doFunction(param, function(myParam)
{
if(myParam)
{
}
else
{
}
});

Related

function that makes another function only executable once in JS

I have been working to create a function that given another function will make that second function only callable once. not unlike the _.once() function.
the desired outcome is the following:
const oneTimeFunction = _.once(function(string) { string.split(''); })
oneTimeFunction('hello')
//returns: 'olleh', and if called again it would have no effect returning the same thing a the original call.
Currently this is what I have:
_.once = function (func) {
var called = 0;
let args = null;
if (arguments.length > 1) {
args = Array.prototype.slice.call(arguments,1);
}
return function () {
if (called === 0) {
console.log('being called');
called ++;
if (!args) {
console.log('without apply');
return func.call(arguments);
} else {
console.log('with apply');
return func.apply(this,args);
}
} else {
console.log('this has been called');
return null;
}
};
};
I am running into a wall as it is returning error type undefined even with everything I have tried. Any help, even to get to where it can call the function regardless of the one time only stipulation? Thanks!
create a variable that count how much this function is called
let count = 0;
function once(str) {
if(count < 1){
count++;
return str.split("").reverse().join("");
}
else return str;
}
console.log(once("hello")); // olleh
console.log(once("hello")); // hello
console.log(once("hello")); // hello
In reading your question, I'm seeing that you would like to always return the first value on subsequent calls:
"if called again it would have no effect returning the same thing a[s] the original call."
So I believe you want to do something like this:
function computeOnce(myFn) {
let origVal = undefined;
return function (...args) {
// if this is not set, this is the first call
if (!origVal) {
// execute the function and store it's return value
origVal = myFn(...args);
}
return origVal;
}
}

Do something only after asynchronous call is finished

I'm trying to create a bounce effect on an image after an synchronous AND an asynchronous call but can't figure out how to do it. The problem I'm having now is that I sometimes get both the bounce effect and afterwards isExecuted becomes true because the asynchronous event takes some time.
My code should work like this:
Iterate over each object in myEnum and execute the following
if myCondition1 is equal too myCondition2 set isExecuted = true
if above is not true, call an asynchronous method which evaluates some stuff, if it's true it will set isExecuted = true.
wait for all above is finished, then if isExecuted still is false, bounce the image.
Here's the code:
var isExecuted = false;
myEnum.each()
{
if (myCondition1 == myCondition2) { //Synchronous
isExecuted = true;
return false; //stop the iteration
}
else {
MyAsyncFunction(myCondition2, function(isTrue) { // Asynchronous
if (isTrue) {
isExecuted = true;
return false; //stop the iteration
}
});
}
});
// Execute this ONLY when above code is finished executing
if (isExecuted == false) {
BounceImage();
}
Please note that the async function is not always executed but the bounce check must always be executed if isExecuted is true.
This whole setup won't work as you want because you cannot stop the iteration from the asynchronous callback. Instead you have to process the array (or whatever myEnum is) asynchronously and do something afterwards. I highly recommend to learn about promises.
function process(array, cb) {
var i = 0;
function p(v) {
return new Promise((resolve, reject) => {
try {
// call the callback, passing in the current value and
// a callback to control execution
cb(v, function next(stop, result) {
if (stop) {
// if stop = true, abort the iteration and resolve the passed in value
resolve(result);
} else if (i < array.length) {
// else if there are more elements left, process them
resolve(p(array[i++]));
} else { // else resolve to the passed in value
resolve(result);
}
});
} catch(e) {
reject(e);
}
});
}
// start with the first element
return p(array[0]);
}
process([1,2,3], function(v, next) {
if (v == 2) {
return next(true, v);
}
next();
}).then(result => console.log(result));
Applied to your code it would look something like
process(myEnum, function(v, next) {
if (myCondition1 == myCondition2) {
return next(true, true);
} else {
MyAsyncFunction(myCondition2, function(isTrue) {
if (isTrue) {
return next(true, true);
}
next();
});
}
}).then(function(isExecuted) {
if (!isExecuted) {
BounceImage();
}
});
Of course you can also use an existing library that allows you to do this. There a many different (potentially more elegant) ways to achieve this.
Instead, use callbacks:
function asyncFunction (a, b, c, callback) {
...
callback();
}
asyncFunction(1, 2, 3, function () {
doSomethingOnceDone();
});
This is a very common practice. It's how most async Chrome APIS do it, just to name one thing.

when javascript function argument are not passed

i am new to JavaScript, i am learning javascript from a book "Visual Quickstart guide",
i am struggling with the following code logic, as function definition shows it expects an argument,
function getNewFile(evt) {
makeRequest(this.href);
evt.preventDefault();
}
but when the function is being called there is not argument being passed to it,
function initAll() {
document.getElementById("makeTextRequest").addEventListener("click",getNewFile,false);
document.getElementById("makeXMLRequest").addEventListener("click",getNewFile,false);
}
i do not understand the default behavour of this function when no arguments have been passed to it,
complete code from the book
window.addEventListener("load",initAll,false);
var xhr = false;
function initAll() {
document.getElementById("makeTextRequest").addEventListener("click",getNewFile,false);
document.getElementById("makeXMLRequest").addEventListener("click",getNewFile,false);
}
function getNewFile(evt) {
makeRequest(this.href);
evt.preventDefault();
}
function makeRequest(url) {
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
if (window.ActiveXObject) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
}
}
}
if (xhr) {
xhr.addEventListener("readystatechange",showContents,false);
xhr.open("GET", url, true);
xhr.send(null);
}
else {
document.getElementById("updateArea").innerHTML = "Sorry, but I couldn't create an XMLHttpRequest";
}
}
function showContents() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
if (xhr.responseXML && xhr.responseXML.childNodes.length > 0) {
var outMsg = getText(xhr.responseXML.getElementsByTagName("choices")[0]);
}
else {
var outMsg = xhr.responseText;
}
}
else {
var outMsg = "There was a problem with the request " + xhr.status;
}
document.getElementById("updateArea").innerHTML = outMsg;
}
function getText(inVal) {
if (inVal.textContent) {
return inVal.textContent;
}
return inVal.text;
}
}
The below code, the 'getNewFile' method is being passed in as a parameter and isn't actually executed until the 'click' even is raised, then it is executed with the expected parameter arguments.
function initAll() {
document.getElementById("makeTextRequest").addEventListener("click",getNewFile,false);
document.getElementById("makeXMLRequest").addEventListener("click",getNewFile,false);
}
In Javascipt, Functions are objects just as numbers, strings, array, etc. If the function name doesn't have "()" double parenthesis after it (with or without out arguments) then it's not being executed right then, but rather being passed as a parameter for future reference/execution.
Here's a couple simple examples of passing Functions as a parameter:
Example 1
function example1() {
alert('hello');
}
function executor1(f) {
// execute the function passed in through argument 'f'
f();
}
executor(example1);
// example1 isn't executed/called until it's called from within executor1
Example 2
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
function alertMath(a, b, f) {
var result = f(a, b);
alert(result);
}
// alerts the message of "3"
alertMath(1, 2, add);
// alerts the message of "6"
alertMath(2, 3, multiply);
// alerts the message of "3"
// this shows a function being defined inline
alertMath(6, 2, function(a, b) {
return a / b;
});
I hope this gives you a little more context surrounding this as to what's going on.
In here :
function getNewFile(evt) {
makeRequest(this.href);
evt.preventDefault();
}
getNewFile is the function reference, getNewFile(parameter) is the function call.
As you can see here :
document.getElementById("makeTextRequest").addEventListener("click",getNewFile,false);
getNewFile (function reference, not function call) is passed on to addEventListener. According to the addEventListener documentation, the second parameter is the listener, which is the function that will be called when the event triggers.

How to check the number of arguments of a callback function before calling the function

I have
function doSomething(callback) {
if (callback.arguments.length == 1) { // Need help here
// Some logic here
callback(obj1);
}
else {
// Some other logic here
callback(obj1, obj2);
}
}
if (someLogic) {
doSomething(function(arg1) { ... });
}
else {
doSomething(function(arg1, arg2) { ... });
}
How can I check the length of the callback's arguments before calling it?
Use callback.length.
The length property on any function tells you the number of named arguments that function expects.

Is it possible to test a sequence of asynchronous function calls with D.O.H

I am trying to use doh.Deferred to write a test that will check the following sequence of events:
login with user A (asynchronous)
log out (synchronous)
login with user A (asynchronous)
The return value of the second callback function is another doh.Deferred object. I was under the impression that the callback chain of d will wait for d2 but it does not. The test finishes before d2.callback is ever called.
Where am I going wrong here?
Does anyone know of a better way for me to test this behavior?
function test() {
var d = new doh.Deferred();
d.addCallback(function() {
Comm.logout(); /* synchronus */
try {
// check with doh.t and doh.is
return true;
} catch (e) {
d.errback(e);
}
});
d.addCallback(function() {
var d2 = new dojo.Deferred();
/* asynchronus - third parameter is a callback */
Comm.login('alex', 'asdf', function(result, msg) {
try {
// check with doh.t and doh.is
d2.callback(true);
} catch (e) {
d2.errback(e);
}
});
return d2; // returning doh.Defferred -- expect d to wait for d2.callback
});
/* asynchronus - third parameter is a callback */
Comm.login('larry', '123', function (result, msg) {
try {
// check with doh.t and doh.is
d.callback(true);
} catch (e) {
d.errback(e);
}
});
return d;
}
This works. The scope of d2 was the problem.
function test() {
var d = new doh.Deferred();
var d2 = new doh.Deferred();
d.addCallback(function() {
Comm.logout(); /* synchronus */
try {
// check with doh.t and doh.is
return true;
} catch (e) {
d.errback(e);
}
});
d.addCallback(function() {
/* asynchronus - third parameter is a callback */
Comm.login('alex', 'asdf', function(result, msg) {
try {
// check with doh.t and doh.is
d2.callback(true);
} catch (e) {
d2.errback(e);
}
});
return d2; // returning doh.Deferred -- waits for d2.callback
});
/* asynchronus - third parameter is a callback */
Comm.login('larry', '123', function (result, msg) {
try {
// check with doh.t and doh.is
d.callback(true);
} catch (e) {
d.errback(e);
}
});
return d;
}

Categories

Resources