This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have a javascript question relating to callback and timeout.
This is an example code snippet I wrote:
var f1 = function(){
var result;
window.setTimeout(
function(){
console.log("timeout in 100ms");
result = 10;
}.bind(this), 100);
return result;
};
So, I want the function to modify the variable result. I used .bind(this) to ensure that it knows what result it.
still, the out put when I run f1() is 9, not 10, which is what I have desired.
Any clues?
Result is a number. Therefore it is returned as the value 9 not a reference to an object.
bind does not have any useful effect in your scenario. bind changes the function context (this).
Returning an object containing the value 10 will work.
var f1 = function(){
var result = { value: 9 };
window.setTimeout(
function(){
console.log("timeout in 100ms");
result.value = 10;}.bind(this), 100);
return result;
};
There are likely better solutions to your problem.
Callbacks:
var f1 = function(valueCallback){
var result;
window.setTimeout(function(){
console.log("timeout in 100ms");
result = 10;
valueCallback(result);
};
Such a function would be used like so:
f1(function(value)) {
console.log(value); // Will print 10 after 100ms.
})
Another alternative, could use Promises:
var f1 = function() {
return new Promise(function(resolve, reject) {
window.setTimeout(resolve.bind(null, 10), 100);
}
}
You would call such a function like so:
f1().then(function(value) {
console.log(value); // Will print 10 after 100ms.
});
You are calling the timeout to modify the value after the function already returned, so it returns the default value for result, then call the timeout, and since the value is limited in scope to the function, you have no means to return it after modification.
What you can do is this
var result = 9;
var f1 = function(){
window.setTimeout(
function(){
console.log("timeout in 100ms");
result = 10;}.bind(this), 100);
return result;};
And then after calling f1 t will return 9 then call result and it will show 10
Related
I am having trouble with the second function. It runs through before there is a value saved in 'w'. Ive tried setTimout() but it did not help. Im trying to implement async/await but im struggling with how it would fit with the code below:
function functionOne(){
var s
chrome.storage.local.get(['prm'], function(result) {
s = result.prm;
return s;
});
}
function functionTwo(){
let w = functionOne();
// second half runs after w is assigned a value (after functionOne is done running).
}
Is async/await the only solution or is there another way of solving it?
async / await is not the only solution. And in any case, you are going to need to create a promise in functionOne
/*async*/ function functionOne(){
var s;
var p = new Promise(function(success) {
chrome.storage.local.get(['prm'], function(result) {
s = result.prm;
success(s);
});
}
return p;
}
function functionTwo(){
let p = functionOne();
p.then(function(s) {
//...
});
}
You need to create a promise to be able to return the results of chrome.log.storage. You can make functionOne async or not. It doesn't change anything.
You would have to use an asynchronous function that does not work all at once.
You could do something like
function functionOne(){
var s
chrome.storage.local.get(['prm'], function(result) {
s = result.prm;
return s;
});
}
async function functionTwo(){
await let w = functionOne();
// second half runs after w is assigned a value (after functionOne is done running).
}
Referenced from here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Note: I would also like to point out that functionOne actually returns an undefined value because inside the chrome.storage.local.get function the callback returns s, so you would need to move the return statement outside of the callback function.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I have following controller and code execution does not wait for the function to bring back values. So some lines of code fail as they are still undefined. How to make sure line execution is in sync.
Also Note: caller function is inside a for loop.
A Controller.js
for (var i=0; i< parseObj.length; i++){
callerFunc: function() {
vc._getValues(A, B, C).then(function (data) {
var vendorNo = data.vendorNo;
var vendorName = data.vendorName
});
// lines of code
}
_getValues: function(A, B, C){
var filters = [
.....
];
var vc = this;
return new Promise(function (resolve, reject) {
service.getDataByFilters(vc, filters,
function (data) {
resolve(data);
},
function (error) {
reject();
}
);
});
the problem is that you need to wait for the result. Service.getMaterial is returning a Promise so when you try to execute the line of code var x = data.Vendor; the variable data is not yet defined.
What you can do is to just call a function inside the promise result (the then function).
I would suggest you learn a little bit more about:
Promise
async/await pattern
I also would like you to know that promise/async-await are not supported by IE in general if I'm not wrong ;)
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have a code like that:
var originalFunction = function() {
return 'some value';
};
var debouncedFunction = _.debounce(originalFunction, 3000);
console.log('debouncedFunction() result: ', debouncedFunction());
console.log('originalFunction() result: ', originalFunction());
(codepen link)
And the result in the console is:
debouncedFunction() result: undefined
originalFunction() result: some value
As you can see, the debounced function doesn't return anything. I understand that it's caused by an internal timer in the debounced function, but is there away around that?
that's because debounced functions are called asynchronously - you can't return a value from them, although you can call another function passing the result:
var originalFunction = function() {
console.log('some value');
// or something like: callback(result)
};
var debouncedFunction = _.debounce(originalFunction, 3000);
console.log('debouncedFunction() result: ', debouncedFunction());
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
The community is reviewing whether to reopen this question as of 9 days ago.
I just want to get the return value from setTimeout but what I get is a whole text format of the function?
function x () {
setTimeout(y = function () {
return 'done';
}, 1000);
return y;
}
console.log(x());
You need to use Promises for this. They are available in ES6 but can be polyfilled quite easily:
function x() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('done!');
});
});
}
x().then((done) => {
console.log(done); // --> 'done!'
});
With async/await in ES2017 it becomes nicer if inside an async function:
async function() {
const result = await x();
console.log(result); // --> 'done!';
}
You can't get a return value from the function you pass to setTimeout.
The function that called setTimeout (x in your example) will finish executing and return before the function you pass to setTimeout is even called.
Whatever you want to do with the value you get, you need to do it from the function you pass to setTimeout.
In your example, that would be written as:
function x () {
setTimeout(function () {
console.log("done");
}, 1000);
}
x();
Better to take a callback for function x and whatever task you want to perform after that timeout send in that callback.
function x (callback) {
setTimeout(function () {
callback("done");
}, 1000);
}
x(console.log.bind(console)); //this is special case of console.log
x(alert)
You can use a combination of Promise and setTimeOut like the example below
let f1 = function(){
return new Promise(async function(res,err){
let x=0;
let p = new Promise(function(res,err){
setTimeout(function(){
x= 1;
res(x);
},2000)
})
p.then(function(x){
console.log(x);
res(x);
})
});
}
I think you want have flag to know event occured or no. setTimeout not return a value. you can use a variable to detect event occured or no
var y="notdone";
setTimeout(function () {
y="done";
}, 1000);
You can access variable y after timeout occured to know done or not
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
setTimeout and “this” in JavaScript
I am trying to put a timeout on an Object. With some test code (see below) I want to decrease the timerPos until it reaches 0. When I use the code below the first time timerInc() is called by startTimer(), it will reach 3 (as expected). When TimerInc() is called by the timeout i will receive 'undefined' for the timerPos variable. What am I doing wrong?
function start(){
var alert = new Alert(3);
alert.startTimer();
}
function Alert(timer) {
this.timerMinutes = timer;
this.timerPos = 0;
this.startTimer = function() {
this.timerPos = this.timerMinutes+1;
this.timerInc();
};
this.timerInc = function() {
if (this.timerPos > 0){
this.timerPos--;
// first time this function gets called timerPos is 3
// the second time when its called by the timeout it
// will be 'undefined'
setTimeout(this.timerInc,1000);
}
};
}
(using this.timerInc() in the timeout instead of this.timerInc does not work for me, neither does using quotes)
You need to bind the "this" variable to another one that you use explicitly since the value of "this" changes based on who is calling the function!
function Alert(timer) {
var that = this; // Store this Alert instance as "that".
this.timerMinutes = timer;
this.timerPos = 0;
// ...
this.timerInc = function() {
// Use the Alert instance "that", not whatever is bound to "this" at runtime.
if (that.timerPos > 0){
that.timerPos--;
setTimeout(that.timerInc, 1000);
}
};
}
The issue is that the setTimeout() function will call its function argument from global scope, not the scope of the enclosing object at the time it is registered. So in global scope the "this" variable is bound to the "global" object (likely the browser window).
You can verify like so:
setTimeout(function(){alert(this);}, 500); // => alerts "[object DOMWindow]"
First of all you should use prototype to declare the methods of your class Alert. And changing the scope of the function you're calling is gonna do the job:
function start(){
var alert = new Alert(3);
alert.startTimer();
}
function Alert(timer) {
this.timerMinutes = timer;
this.timerPos = 0;
}
Alert.prototype.startTimer = function() {
this.timerPos = this.timerMinutes+1;
this.timerInc();
};
Alert.prototype.timerInc = function() {
if (this.timerPos > 0){
this.timerPos--;
console.log(this.timerPos);
setTimeout(function(_this){_this.timerInc()},1000,this);
}
};
DEMO: http://jsfiddle.net/kmendes/HNYKa/1/