I know I'm going to post this and then get it working, not to mention the title but...
I'm in a situation where I need to do some async code to each element in an array that I'm given, and then do some checks after all of them have finished. Normally, if I would use async.js here, however the way I'm doing it isn't getting my the results I want.
So this is my logic, I figure I can create an array of functions, however the way I'm doing this seems to have async.js returning me a list of functions in the result.
findLeadThatCanBeTaken : (leads, user, manualTake, cb) =>
if(leads.length == 0) then return cb(null, null)
funcArr = []
self = this
for lead in leads
fun = (callback) ->
console.log(lead.state)
State.get lead.state, (e, state) ->
if !state or state.canBeCalled(self.currentTime())
return callback(null, lead._id.toString)
return callback(null, null)
funcArr.push(fun)
async.parallel funcArr, (e, r) ->
if (e)
return cb(message:'No leads can be called at the current time', null)
id = _.compact(r)
id = r[0] if r.length
if (!id || !id.length)
return cb(message:'No leads can be called at the current time', null)
lead = _.filter leads, (l) -> return l._id.toString() == id
# Code handling
#takeLead(lead, user, cb)
I'm 90% sure the issue is this array I am creating isn't being assigned like I think it is, but I'm not sure. Anyone know what I'm doing wrong here?
I'd guess that you have a classic "closure inside a loop" problem:
for lead in leads
fun = (callback) ->
# some stuff that uses 'lead'...
The problem is that all your fun functions will have a reference to exactly the same lead and when those functions execute, lead will refer to the last value it had in the loop.
From the fine manual (bottom of that section):
When using a JavaScript loop to generate functions, it's common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions don't just share the final values. CoffeeScript provides the do keyword, which immediately invokes a passed function, forwarding any arguments.
Sound familiar? You probably want to get the value of lead on each iteration rather than just dragging around lead itself with something like this:
for lead in leads
do (lead) ->
fun = (callback) ->
# What you have now...
Related
Issue Description
I'm currently trying to make updates on passwords using sequelize.fn.
I've seen numerous sites, including the Sequelize's manual, yet I found too few articles that approaches my case, and none of them seems to solve it.
Moreover, the function to encrypt the passwords need nested function, so I need to gradually construct the nested function
by putting the successive arguments into variables.
I have not found anything on constructing the functions, thus using sequelize.fn outside the arguments of the functions find and updates.
Additional context
In my case, " crypt('password', gen_salt('bf', 4)) " (in Postgres) needs to become
sequelize.fn('crypt', 'password', sequelize.fn('gen_salt', 'bf', 4)) and to be stored into a variable
When I inject it into the update function, an Fn Object is injected, and the result in the database seems to be a memory address instead of the result of the crypt function.
I may post a code example so you can have a better understanding of what I'm trying to do and I think should be added into the documentation
I did not made this doc issue to resolve my issue, only to point out what I think is lacking in the documentation
I will ask StackOverflow for help regarding my issue.
//Take a format and a value, and applies the functions inside the format onto the value
function recursSequelizeFn (format, value) {
const sequelize = db.sequelize;
let nextId = 0;
let matches;
let finalArgs = {};
//The RegEx finds the function calls of which parameters aren't functions themselves
//As the format string is modified on each loop, I need to initialize the RegEx on each loop
while ((matches = (/(\w+)\(([^(,)]+)?(?:,([^(,)]+))*\)/g).exec(format)) !== null) {
//matches[0] is the whole expression
//matches[1] is the function's name
//matches[>=2] are the arguments
let func = matches[1];
let args = matches.slice(2);
for (let argNo in args) {
//Transforms DB's columns into Sequelize-interpreted columns
//I do not check the column that is found, because I do not have others columns than the one that is being treated
args[argNo] = args[argNo].replace(/seqCol_(\w+)/g, (correspondance, p1, decalage, chaine)=>{return value;});
//If the parameter was previously saved, we replace its reference by its value
args[argNo] = args[argNo].replace(/(#\d+)/g, (correspondance, p1, decalage, chaine)=>{return finalArgs[p1];});
}
//finally, we save the value of the function and replace the whole expression by a reference
finalArgs['#'+nextId]=sequelize.fn(func, ...args);
format = format.replace(matches[0], '#'+nextId);
nextId++;
}
//When the treatment is finished, we return the last value saved into the array
//Or we return the original value if we have not made any change (the array will be empty)
return finalArgs['#'+(nextId-1)]||value;
}
Object.keys(req.message.attributes).map((key)=>{
//req.message.attributes[key] contains the formatting needed to be put onto the value
//e.g. crypt(password, gen_salt('bf', 4))
//req.body[key] contains the value
//e.g. '1234'
let seqValue = util.recursSequelizeFn(req.message.attributes[key], req.body[key]);
req.body[key] = seqValue;
});
//mainModel is a sequelize model
mainModel.update(req.body, {where: {id:req.params.id}, logging:console.log})
.then() //...
I came across the following code for a callback function. I understand the code, but I can't wrap my head around it. It just seems so counterintuitive.
function greet(name,callback1){
callback1(name)
}
greet("John Cena", function (somerandomName) {
console.log(somerandomName);
return someRandomName;
}); // Output is John Cena and undefined.
This is what I have understood from the code:
We define a function greet, which takes 2 parameters name and callback1. Then we say that callback1's parameter is name. We don't return anything in the greet function, why?
And when we invoke the greet function we pass the 2nd parameter as an Anonymous function whose parameter is someRandomName. Then we console.log(someRandomName).
I added the return someRandomName, but this return did not work and I got the printed statement followed by undefined
Can someone please explain this in simple words, This just seems so counterintuitive.
So I think it is important to understand that functions themselves can be parameters.
In this example you pass a string as the first parameter and then a function that takes that string as a parameter as the second parameter.
Functions do not always need to return something. Often a function might perform a manipulation on the dom, fetch data, configure something or alter pre existing variables. Of course you can return something if that is what is needed.
Adding return like you did does not do much. In order to actually return the name value you would have to write the original function like this.
function greet(name,callback1){
return callback1(name)
}
Then you could do something like this
var wrestler = greet("John Cena", function (somerandomName) {
console.log(somerandomName);
return somerandomName;
});
console.log(wrestler) // prints John Cena
Its sort of an weird example since it serves no real purpose. Something like this might help you see whats going on.
function greet(name, callback) {
callback(name)
}
greet('John Cena', function(name){
console.log('Hello ' + name) // prints Hello John Cena
})
OR return something and use it to manipulate dom
function greet(name, callback) {
return callback(name)
}
var greeting = greet('John Cena', function(name){
return 'Hello ' + name
})
document.getElementById('message').innerHTML = greeting
// somewhere in HTML...
<h1 id='message'></h1>
Either way at least we are doing something to the first parameter now. And the things that you can do with callbacks are limitless.
Callbacks are a fundamental feature of javascript. They come into play alot when the first part of the function is asynchronous, such as a call to an api or database. In this case the first part would be the call to the database and the callback will not be fired until a value is obtained from the initial call. Recently, this callback pattern is being used less due to Promises, but callbacks are still useful.
So an example of a generic api call from a frontend to a backend. This would typically be done using the Fetch Api or with a library like Request or Axios. Just remember, the first function that is calling an endpoint takes some amount of time to execute and get data. The callback will not fire until that data is returned. Of course there would be a function on the backend that sends either an error or data back to the callback. I dont want to over complicate things, rather just give an idea of what callbacks are often used for.
function getDataFromBackend(endPoint, callback) {
callback(error, data)
}
getDataFromBackend('/api/user', function(error, data) {
if (error) {
// handle error - show user error message in ui, etc
}
// do something with data - such as display welcome message to user, etc
})
I would suggest working with callbacks for practice. I find that when I use Node, or build an app with a frontend and backend I implement callbacks a lot for, since there is a lot of asynchronous communication happening. Hope I answered your questions.
First, you have return someRandomName but your parameter is called somerandomName. Variables are case sensitive; that's why your return value is different from what you want.
Your question is Why don't we return anything in the greet function. The answer is "I have no idea." You could return something. Some functions return things; some functions don't. That has nothing to do with the callback arrangement here.
function greet(name,callback1){
return callback1(name)
}
var finalResult = greet("John Cena", function (someRandomName) {
console.log(someRandomName);
return someRandomName;
});
Now finalResult will be "John Cena".
If it helps at all, anywhere you're using an anonymous function, you could just as easily use a named function. (It's often uglier in practice, but for the sake of understanding the concepts...)
function greet(name,callback1){
return callback1(name)
}
function myGreeterFunction(someRandomName) {
console.log(someRandomName);
return someRandomName;
});
var finalResult = greet("John Cena", myGreeterFunction);
Now it's perhaps easier to see that callback1(name) is the same thing as saying myGreeterFunction(name) in this case.
This is a pretty dated approach to JavaScript and you are totally right that it's counter intuitive. In this particular example there's no advantage of writing this with a callback and probably should be written as a promise,
greet("John Cena")
.then(() => {
return 'Next Action'
})
.then(nextAction => {
console.log(nextAction)
})
And as #mark-meyer pointed out this approach would be required if you had an asynchronous event.
Actually an AWS Lamda function actually has an optional callback defined as it's third argument. exports.myHandler = function(event, context, callback) {}. Which to be brutally honest I think is only there to cover cases where third party libraries aren't promised based.
Whilst passing a callback to a function is probably never the correct approach, there's still cases where passing a function to a function is valuable. Perhaps in a pub/sub system.
const events = {}
function subscribe (event, func) {
if (events[event]) {
events[event].push(func)
} else {
events[event] = [func]
}
}
function publish (event) {
if (events[events]) {
events[event].forEach(func => func())
}
}
And if you are writing with a fp approach link in RamdaJs chaining functions is going to be a huge part of what you write.
Does that clear things up a bit #pi2018?
The general technique is called continuation-passing style – contrast with direct style.
The technique does allow for some interesting programs to emerge. Below, we have two ordinary functions add and mult. We write two programs using cont which allows us to string these functions together, where each step is
the continuation of the one before it.
const cont = x => k =>
cont (k (x))
const add = x => y =>
x + y
const mult = x => y =>
x * y
cont (1) (add (2)) (mult (3)) (console.log) // 9
// 1 ->
// x => 2 + x
// cont (3) ->
// x => 3 * x
// cont (9) ->
// x => console.log (x)
// cont (undefined)
We can sequence as many operations as needed –
const cont = x => k =>
cont (k (x))
const add = x => y =>
x + y
const mult = x => y =>
x * y
cont (2) (mult (2)) (mult (2)) (mult (2)) (mult (2)) (console.log) // 32
// 2 ->
// x => 2 * x
// cont (4) ->
// x => 2 * x
// cont (8) ->
// x => 2 * x
// cont (16) ->
// x => 2 * x
// cont (32) ->
// x => console.log (x)
// cont (undefined)
Continuation-passing style can be used to implement concurrent programs, but JavaScript provides a better native concurrency primitive now, Promise. There's even new async and await syntax to make working with Promises easier.
As wikipedia notes, continuation-passing style is used more by compilers and less by programmers. If you're trying to write concurrent programs, I would highly recommend you use Promises instead. Later versions of Node include util.promisify which allows users to convert a continuation-passing style function to a Promise-returning async function.
I stumbled into this problem recently and after a while of reading around I couldn't find an answer that satisfies this use case in particular.
I am trying to achieve the following behaviour in javascript
// Lets assume we have some variable defined in global scope
var a = {val: 0}
// What I want here is a function that sets a.val = newVal
// and then calls the callback.
var start = function(newVal, cb) {
???
}
// such that
start(1, function() {
setTimeout(function() {
console.log(a.val) // 1
}, 1000)
})
// and
start(2,function () {
console.log(a.val) // 2
})
// but in the original scope
console.log(a.val) // 0
In other words i am looking for a way to "wrap" a callback in a different global scope. I am aware that you can do something similar passing an environment around or using this; but such methods always force the callback functions to refer to the environment explicitly, turning the callback code into something like
start(2,function () {
console.log(env.a.val) // 2
})
I am specifically looking for a solution that preserves the possibility to use the global reference directly from within the callback of start.
Feel free to use any ES6/ES7 feature that can somehow be shimmed in or is compatible with node, this is not meant for production code just a fun exercise.
EDIT:
I will explain the general problem since many people suggested this solution might not be what I am actually looking for.
I recently learned about STM (https://wiki.haskell.org/Software_transactional_memory)
and wanted to play around with a similar idea in js.
Of course js runs on a single thread but the idea was to provide the same level of isolation to different callbacks running in atomic blocks.
The user has some kind of shared transactional variable. Operations on this
variable must be wrapped in atomically blocks. What happens under the hood is that operations in the atomically block are not performed on the actual TVar but on some MockTVar which simply records all the reads and writes in a log.
When you call the done the log is checked to see if the operations performed are consistent with the current state of the TVars; if it is the updates now performed on the actual TVars and we are done (this is called a commit). If it is not the log is discarded and the callback is run again. This is a small example of the code
var x = new TVar(2)
// this is process a
process.nextTick(function() {
atomically(x, function(x, done) {
a = x.readTVar()
setTimeout(function() {
x.writeTVar(a+1)
console.log('Process a increased, x = ', x.readTVar())
done()
}, 2000)
})
})
// this is process b
process.nextTick(function() {
atomically(x, function(x, done) {
var a = x.readTVar()
x.writeTVar(a+1)
console.log('Process b increased, x = ', x.readTVar())
done()
})
})
In this example process a will try to commit but since process b changed the value of x (and committed that change before a) the commit will fail and the callback will run once more.
As you can see I am returning the mockTVars in the callback, but i find this a bit ugly for two reasons:
1) If you want to lock more than one variable (and you generally do) i have no choice but to return an array of mockTVars forcing the user to extract them one by one if he wants to use them cleanly.
2) It is up to the user to make sure that the name of the mockTVar which is passed to the callback matches the name of the actual TVar if he wants to be able to reason about whats happening without losing his mind. What I mean is that in this line
atomically(x, function(x, done) {..})
It is up to the user to use the same name to refer both to the actual TVar and the mocked TVar (the name is x in this example).
I hope this explanation is helpful. Thanks to everybody that took the time to help me out
I still wish you would describe the actual problem you're trying to solve, but here's one idea, that makes a copy of the global object, passes it to the callback and the callback can use the same name as the global and then it will "override" access to the global for that scope only.
var a = {val: 0, otherVal: "hello"} ;
function start(newVal, cb) {
var copy = {};
Object.assign(copy, a);
copy.val = newVal;
cb(copy);
}
log("Before start, a.val = " + a.val);
start(1, function(a) {
// locally scoped copy of "a" here that is different than the global "a"
log("Beginning of start, a.val = " + a.val) // 1
a.val = 2;
log("End of start, a.val = " + a.val) // 2
});
log("After start, a.val = " + a.val);
function log(x) {
document.write(x + "<br>");
}
Scenario: I'm searching for a specific object in a deep object. I'm using a recursive function that goes through the children and asks them if I'm searching for them or if I'm searching for their children or grandchildren and so on. When found, the found obj will be returned, else false. Basically this:
obj.find = function (match_id) {
if (this.id == match_id) return this;
for (var i = 0; i < this.length; i++) {
var result = this[i].find(match_id);
if (result !== false) return result;
};
return false;
}
i'm wondering, is there something simpler than this?:
var result = this[i].find(match_id);
if (result) return result;
It annoys me to store the result in a variable (on each level!), i just want to check if it's not false and return the result. I also considered the following, but dislike it even more for obvious reasons.
if (this[i].find(match_id)) return this[i].find(match_id);
Btw I'm also wondering, is this approach even "recursive"? it isn't really calling itself that much...
Thank you very much.
[edit]
There is another possibility by using another function check_find (which just returns only true if found) in the if statement. In some really complicated cases (e.g. where you don't just find the object, but also alter it) this might be the best approach. Or am I wrong? D:
Although the solution you have is probably "best" as far as search algorithms go, and I wouldn't necessarily suggest changing it (or I would change it to use a map instead of an algorithm), the question is interesting to me, especially relating to the functional properties of the JavaScript language, and I would like to provide some thoughts.
Method 1
The following should work without having to explicitly declare variables within a function, although they are used as function arguments instead. It's also quite succinct, although a little terse.
var map = Function.prototype.call.bind(Array.prototype.map);
obj.find = function find(match_id) {
return this.id == match_id ? this : map(this, function(u) {
return find.call(u, match_id);
}).filter(function(u) { return u; })[0];
};
How it works:
We test to see if this.id == match_id, if so, return this.
We use map (via Array.prototype.map) to convert this to an array of "found items", which are found using the recursive call to the find method. (Supposedly, one of these recursive calls will return our answer. The ones which don't result in an answer will return undefined.)
We filter the "found items" array so that any undefined results in the array are removed.
We return the first item in the array, and call it quits.
If there is no first item in the array, undefined will be returned.
Method 2
Another attempt to solve this problem could look like this:
var concat = Function.prototype.call.bind(Array.prototype.concat),
map = Function.prototype.call.bind(Array.prototype.map);
obj.find = function find(match_id) {
return (function buildObjArray(o) {
return concat([ o ], map(o, buildObjArray));
})(this).filter(function(u) { return u.id == match_id })[0];
};
How it works:
buildObjArray builds a single, big, 1-dimensional array containing obj and all of obj's children.
Then we filter based on the criteria that an object in the array must have an id of match_id.
We return the first match.
Both Method 1 and Method 2, while interesting, have the performance disadvantage that they will continue to search even after they've found a matching id. They don't realize they have what they need until the end of the search, and this is not very efficient.
Method 3
It is certainly possible to improve the efficiency, and now I think this one really gets close to what you were interested in.
var forEach = Function.prototype.call.bind(Array.prototype.forEach);
obj.find = function(match_id) {
try {
(function find(obj) {
if(obj.id == match_id) throw this;
forEach(obj, find);
})(obj);
} catch(found) {
return found;
}
};
How it works:
We wrap the whole find function in a try/catch block so that once an item is found, we can throw and stop execution.
We create an internal find function (IIFE) inside the try which we reference to make recursive calls.
If this.id == match_id, we throw this, stopping our search algorithm.
If it doesn't match, we recursively call find on each child.
If it did match, the throw is caught by our catch block, and the found object is returned.
Since this algorithm is able to stop execution once the object is found, it would be close in performance to yours, although it still has the overhead of the try/catch block (which on old browsers can be expensive) and forEach is slower than a typical for loop. Still these are very small performance losses.
Method 4
Finally, although this method does not fit the confines of your request, it is much, much better performance if possible in your application, and something to think about. We rely on a map of ids which maps to objects. It would look something like this:
// Declare a map object.
var map = { };
// ...
// Whenever you add a child to an object...
obj[0] = new MyObject();
// .. also store it in the map.
map[obj[0].id] = obj[0];
// ...
// Whenever you want to find the object with a specific id, refer to the map:
console.log(map[match_id]); // <- This is the "found" object.
This way, no find method is needed at all!
The performance gains in your application by using this method will be HUGE. Please seriously consider it, if at all possible.
However, be careful to remove the object from the map whenever you will no longer be referencing that object.
delete map[obj.id];
This is necessary to prevent memory leaks.
No there is no other clear way, storing the result in a variable isn't that much trouble, actually this is what variables are used for.
Yes, that approach is recursive:
you have the base case if (this.id==match_id) return this
you have the recursive step which call itself obj.find(match_id) { ... var result = this[i].find(match_id); }
I don't see any reason, why storing the variable would be bad. It's not a copy, but a reference, so it's efficient. Plus the temporary variable is the only way, that I can see right now (I may be wrong, though).
With that in mind, I don't think, that a method check_find would make very much sense (it's most probably basically the same implementation), so if you really need this check_find method, I'd implement it as
return this.find(match_id) !== false;
Whether the method is recursive is hard to say.
Basically, I'd say yes, as the implementations of 'find' are all the same for every object, so it's pretty much the same as
function find(obj, match_id) {
if (obj.id == match_id) return obj;
for (var i = 0; i < obj.length; ++i) {
var result = find(obj[i], match_id);
if (result !== false) return result;
}
}
which is definitely recursive (the function calls itself).
However, if you'd do
onesingleobjectinmydeepobject.find = function(x) { return this; }
I'm not quite sure, if you still would call this recursive.
In Javascript, I sometimes want to return a value from a scope that isn't the current function. It might be a block of code within the function, or it might be an enclosing function as in the following example, which uses a local function to recursively search for something. As soon as it finds a solution, the search is done and the outer function should just exit. Unfortunately, I can't think of a simpler way to do this than by hacking try/catch for the purpose:
function solve(searchSpace) {
var search = function (stuff) {
var solution = isItSolved(stuff);
if (solution) {
throw solution;
} else {
search(narrowThisWay(stuff));
search(narrowThatWay(stuff));
};
};
try {
return search(searchSpace);
} catch (solution) {
return solution;
};
};
I realize one could assign the solution to a local variable and then check it before making another recursive call, but my question is specifically about transfer of control. Is there a better way than the above? Perhaps involving label/break?
Edit: since the answers to date are variations of "ew that's bad
you're not supposed to do that", let me add some necessary
context. I'm hacking on an open-source compiler that targets
Javascript. No one is going to write this code by hand, so please
don't tell me "this is a bad programming technique". What I want is a
better code generation technique. The question is whether anyone has
any clever hack for exploiting Javascript to get more flexible control
transfer.
The reason assigning the result to a local variable and checking it is
ruled out is because that requires understanding the code in a way
that is hard for a compiler to do.
It seems I stand corrected on the intent of the question. If statements are are a useful and readable way to structure code and make it flow however you want to. There's a reason goto was taken out of so many languages, because you don't need it. And it seems like, based on your example code, you're using a try-catch block as a form of goto. If you don't want certain things to run then use if statements or equivalents:
function solve(searchSpace) {
function search = function (stuff) {
//|| will only return the first value if that value is truthy, subsequent values will be ignored
return isItSolved(stuff) || (search(narrowThisWay(stuff)) || search(narrowThatWay(stuff)));
};
return search(searchSpace);
};
I know of no way to break out of function calls like you want. You can break out of loops using labels, but it doesn't seem that's much help to your situation. Other than that, I don't think JavaScript has any such ability beyond your use of exceptions
function solve(stuff) {
return isItSolved(stuff) || solve(narrowThisWay(stuff)) || solve(narrowThatWay(stuff));
}
Bob's way is good... exept that he uses twice the function statement (and that he uses ; after a function delaration without an assignment)... and that as we can do it that way, function solve actually is function search.
PS : This code will epically fail if the isItSolved, narrowThisWay or narrowThatWay functions can return a value evaluated to false as a positive result. In this cas, you would have to use ? : statement in order to check if all responses are !== undefined.
PS2: And of ourse, if these function can send an error, you have to catch it...
It looks like you're doing a fairly straightforward recursive search in your example. Why not just use "return"?
function solve(searchSpace) {
var search = function (stuff) {
var solution = isItSolved(stuff);
if (solution) {
return solution;
} else {
solution = search(narrowThisWay(stuff));
if (solution) {
return solution;
}
return search(narrowThatWay(stuff));
};
};
return search(searchSpace);
};
I suppose it could be that there are other constraints you haven't mentioned, but it's in general possible to turn any control flow into a set of nested (or recursive) functions, with appropriate return values.
The cleanest way would be to use a continuation, but you don't have that efficiently in JS (a few JS engines support continuations, but for the rest there's only CPS, which cries out for tail calls). In C, you could use setjmp/longjmp. In Common Lisp, you could use conditions (which include the functionality of exceptions plus much more). In JS, exceptions are the only non-local control flow option you have available.
You can programmatically transform a program into another that uses CPS.
function solve(searchSpace, isItSolved, isBase, narrowThisWay, narrowThatWay) {
function search(stuff, k) {
solution = isItSolved(stuff);
if (solution) {
return solution;
} else if (isBase(stuff)) {
return k();
} else {
return search(narrowThisWay(stuff), function() {
return search(narrowThatWay(stuff), k);
});
};
};
return search(searchSpace, function(val) {return val});
};
var arr=[1, 2,9,72,0,34,5,33,24,62,89,90,30,54,590,23,59,62,73];
solve(arr, function(a) {return (a.length==1 && a[0] == 5) ? a[0] : false;},
function (a) {return a.length < 2; },
function (a) {return a.slice(0, a.length / 2);},
function (a) {return a.slice(a.length / 2);}
);