I'm having an issue with this piece of code:
function aFunction(){
....
var deferred = $q.defer();
debounce(function () {
deferred.resolve(service.subscribe0(data));
}, 350);
return deferred.promise;
}
The returned promise is never resolved. Debounce function is a 3rd party function with a lot of downloads from NPM, so I can be sure it works.
Can it be because the return statement "removes" the scope of the function? How can I avoid this and resolve the promise?
You misunderstand what debounce() does.
debounce() is a function that accepts a function, and returns a function. The returned function will only call the passed callback after N milliseconds of silence (that is, if you call the debounced function very quickly in sequence, only the last call will take effect, after the time elapses).
debounce() itself doesn't call the function you pass it. So, deferred.resolve() never gets called.
I would expect something like:
const getData = data => Promise.resolve( service.subscribe0( data ));
grid.addEventListener( 'scroll', debounce( getData, 350 ));
We want the grid to update itsself on scroll, but debounce it so it won't flood the service with calls. So we have to debounce the function tied to the scrolling instead of the data call, since there's no link between two different data calls.
Related
const getData = (cb) => {
setTimeout( () => {
cb({ data: ['there', 'is', 'stuff', 'here'] })
}, 100)
}
getData( data => {
console.log(data);
});
Here is the example of the javascript callback. Could some one let me know how this functions is executed into the javascript callback?
Here what is the function inside getData(cb) ? How it will be executed ? How the functions is passed as callback inside cb and return to the console.log
Regards.
The function inside getData is a callback being passed to setTimeout, which is one way to schedule a call to a function to happen in the future. In this case, it's asking for that callback to happen roughly 100ms later. getData returns before that happens.
The setTimeout callback is a closure¹ over the context where it's created, which means it has access to cb even after getData has returned. So when the browser's timer calls the callback, the callback can call cb. The call to cb uses an object literal to create an object to pass to cb.
In the call to getData, the author is passing a function as cb that logs the data it receives.
So:
getData is called, passing in a function that will log the argument it gets.
getData calls setTimeout to schedule a callback in about 100ms, passing in another function for the timer to call.
getData returns.
About 100ms later, the browser's timer subsystem triggers a call to the callback passed to setTimeout.
That callback creates an object and calls cb, passing the object to it.
That callback (the one passed to getData) logs the data object it receives.
¹ "closure" — see: SO, my anemic blog
In order to understand the code you can just simplify it by naming the anonymous functions. One example could be:
function logData(data) {
console.log(data);
}
const getData = (cb) => {
// `cb` is `logData` function when `getData` is called
function timeoutCallback() {
var data = { data: ['there', 'is', 'stuff', 'here'] };
cb(data);
}
setTimeout(timeoutCallback, 100)
}
getData(logData);
Does that make sense?
1- first global execution context created
2- get data function will be called then it will wait for 10 seconds inside the event loop then it will be come to execution context and printed to console.
I have:
this.selectedItem.subscribe(model => {
this.currentEditor(this.editors.find(e => e.canRender(model)));
this.currentEditor().render(model);
});
where this.selectedItem already has a value.
Is it possible to run callback (but leaving it anonymous) immediately after subscribing?
You can call valueHasMutated on this.selectedItem, so
this.selectedItem.valueHasMutated()
However this not just runs your callback but also notify everybody else, e.g bindings, computeds etc.
So you are propably better to have a named function and call it when it is needed and use that also in the subscribe.
You can extract function into a variable and call it:
var changeHandler = (model) => {
this.currentEditor(this.editors.find(e => e.canRender(model)));
this.currentEditor().render(model);
};
this.selectedItem.subscribe(changeHandler);
changeHandler();
I have an issue with js promises that I hope someone can help me with. The function myFunction below performs a $.ajax call and therefore returns a promise. As I need to hand control back to the browser in order to show the refreshed div that this function updates as I recurse, I'm calling a setTimeout as follows:
var nextBitOfWork = function () {
return myFunction(email);
};
setTimeout(nextBitOfWork, 0);
where myFunction (which recurses) now returns a promise when it's done doing it's $.ajax call.
If I simply call:
return myFunction(email);
without the setTimeout function construct above, the promise is passed through and all my promises are captured and allow me to get the array output I need and everything works great when recursion ends. But without the setTimeout I don't get the browser refresh. Using it as above I get the div update refresh displaying, but seem to lose the promise and so the script continues and I don't get to fill the array that myFunction builds as it recurses.
Any thoughts on how to make sure the setTimeout passes on the promise reliably so that I build the response array and display the div updates as I do so?
Thanks, in advance, for your help!
OK - now have the following:
var func = function () {
myFunction(email);
};
return refreshscreen(func,0);
where refreshscreen is:
function refreshscreen(func,time) {
var timer = $.Deferred();
setTimeout(function () {
return func().then(timer.resolve());
}, time);
return timer.promise();
}
Still the same issue - although the browser renders the div, the array I build with myFunction for the collected $.ajax responses is only 1 element in length - though it recurses 20 times! Without the call to refresh screen, the array builds fine, but the browser never renders the div's as we recurse!
setTimeout does not return the value returned by the function that you pass in. (It returns a value you can use to stop the timeout by passing it in to clearTimeout)
So in order to receive the returned value from myFunction just wrap it in a function in your call to setTimeout.
setTimeout(function () {
var promise = myFunction(email);
// do something with promise...
}, 0);
I have the following code:
function doSomething() {
//xhr here
setTimeout(function() {
var value = 42;
}, 10);
return {
then: function(callback) {
callback(value);
}
};
}
doSomething().then(function(result) {
log("got a result", result);
});
And can't figure out how to access the value.
I need this to be promise-based solution in order to use in multiple places
JSFidle link
Update:
We are not using any libraries in that projects
There are a couple of problems there:
value is local to the function you're passing into setTimeout, because that's where you've declared it. You could fix this issue by declaring it in doSomething instead.
The bigger issue is that what you have there isn't a promise, it's just a function that returns an object when you call it that has a then method. Here's the order in which things happen:
You call doSomething
It sets a timer to set a value.
It creates an object with a then function.
It returns the object.
You call the then function immediately.
then tries to access value (which it can't because of the declaration issue, but would be a problem anyway).
Some time later, value is set by the callback when the timer fires.
To be a promise, the then function on object you return would have to store a reference to the callback passed into it, and call the callback later, when value has been set (e.g., the promise has been fulfilled).
Rather than implementing your own promises library, I'd suggest using one of the several that have already been written and debugged.
I'm just pointing out, that in order to "fix" your issue you need to return the then this way:
function doSomething() {
//xhr here
return {
then: function(callback) {
setTimeout(function() {
callback(42); // callback from within the async action
}, 10);
}
};
}
doSomething().then(function(result) {
log("got a result", result);
});
Please read TJ's answer and consider using a promise library - also consider reading this post that explains how promise resolution looks like.
Namely: Your then needs to in turn return a promise when called (rather than just set a timeout) for chaining, and the callback should be assimilated before waiting for it.
In my code, I have an array of function calls. I loop over these calls and use .apply() to call them. The problem is that if the call of the new function takes any sort of time, the loop will .apply() and call the next function before the prior function is finished. >.< Here is an example:
function someFunc(element, calls){
if(calls.length){
fn = calls[0];
calls.shift();
fn.apply(element, args);
someFunc(element, calls);
}
}
So if there was a callback on the apply function then this could work how I want it to. i.e.
function someFunc(element, calls){
if(calls.length){
fn = calls[0];
calls.shift();
fn.apply(element, args, function(){
someFunc(element, calls);
});
}
}
I also have a question about calling someFunc inside of a callback function. The functions in my calls array affect my element variable. So I want to make sure after it gets changed that it gets passed to someFunc in the callback so the next function can manipulate it as well. Sometimes I just get confused with the this context. :)
If it helps, I am using jQuery. I know how to add callbacks to jQuery methods but I don't know how to do that when I'm dealing with native JavaScript code. How can I add a callback to the .apply() method?
Make sure that every function you call returns a promise. You can then "wait" for that promise to be "resolved" before continuing with the next function in your list:
function someFunc(element, calls) {
if (calls.length) {
var fn = calls.shift();
fn.apply(element, args).done(function(el) { // what's args?
el = el || element; // default to previous element if necessary
someFunc(el, calls);
});
}
}
with each function looking something like:
function myFunc1(el) {
var def = $.Deferred();
// do something async, and "resolve" the deferred object in the async callback
...(function() {
def.resolve(el); // this "el" will get passed to the next function
});
return def.promise();
}
If the asynchronous task is an AJAX call you can just return the jqXHR result of $.ajax directly instead of creating a new deferred object.