This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
So I have this function which I would like to run:
const normal = () => {
return 'working
}
I can log its output and it works fine:
console.log(normal()) // does output: 'working'
Now I would like to run a function delayed which is exactly the same as normal only it takes 3 seconds before returning
I would like to be able to log this function call but only after 3 seconds, I am understandably logging undefined at the moment and have a feeling that it might be possible to do. Anyway I want the following to happen, the function to hang for 3 seconds, then return data:
console.log(delayed()) // should output: 'working'
My attempts:
const toReturn = () => {
return 'working'
}
const runner = (cb) => {
setTimeout(cb, 1000)
}
export const delayed = () => {
return runner(toReturn)
}
console.log(delayed()) // currently outputting: undefined
undefined is because I am not returning anything from runner, if I return setTimout... in runner, I simply get the whole setTimout function, which is pretty useless.
I know you can simply log after 3 seconds within a callback, but I would like to log what is returned from a setTimeout
When you call console.log (or anything else) it's going to take that action then. JS is not like some languages where you pause code execution.
If you want the console.log to be delayed then you need to delay the actual call to console.log, not the return of the value you're logging.
The simplest way would be something like this:
function delayedLog(seconds)
{
setTimeout(function(){
var val = getSomething(); // <- pretend this returns "later"
console.log(val); // <- after 3 seconds logs "later"
}, seconds*1000);
}
console.log('now');
delayedLog(3);
Related
I am new to javascript and reading about closures currently. I was trying to implement an example to better understand the concept.
This is the snippet:
function getValue() {
let a = 0
const runner = async () => {
a += 1
}
setInterval(runner, 100)
return () => {
return a
}
}
let value = getValue()
console.log(value()) -----> logging statement 1
// some long operation
console.log(value()) -----> logging statement 2
However, the output that I see is:
1
1
I expected the two logging statements to output two different values. My understanding is that once getValue() is called, the runner function would execute at regular intervals. The variable a would get updated and hence the 2nd console.log should have printed an incremented value of a.
You are almost there except missed the main part.
Operations are happening too fast. It does not take 100 milliseconds to run the second iteration so the value remains the same.
Try to wait at least 100 milliseconds since the interval you have needs that amount of time to increment.
As shown in the example below.
function getValue() {
let a = 0
const runner = async () => {
a += 1
}
setInterval(runner, 100)
return () => {
return a
}
}
let value = getValue()
console.log(value())
// operations are happening too fast
setTimeout(() => console.log(value()), 100);
setTimeout(() => console.log(value()), 200);
setTimeout(() => console.log(value()), 300);
function getValue() {
let a = 0
const runner = () => {
a += 1
console.log("Runner's A: " +a)
}
setInterval(runner, 100)
return () => {
return a
}
}
let value = getValue()
console.log(value());// -----> logging statement 1
// some long operation
console.log(value());// -----> logging statement 2
https://jsbin.com/geponejuba/edit?js,console,output
as pointed out above js is single threaded, and so the way it works is, your log statements are executed 1st and if there is nothing else to do, then setTimeout/setInterval are executed (this is a extremely simplified statement, You can read about "Event loop" for a detailed version)
on the example jsbin i shared you can see the setInterval is getting called and is indeed updating the value.
JavaScript async/await and Synchronous JavaScript both look similar and making the program to wait, then what is the use of async/await ?
For example
Synchronous JavaScript Code
function getStudentList() {
return ['Adam', 'Ben'];
}
function findStudent(who) {
const list = getStudentList();
const found = list.some(student => student === who);
console.log(found); // logs true
}
findStudent('Adam');
Asynchronous JavaScript using async/await
function getStudentList() {
return new Promise(resolve => {
setTimeout(() => resolve(['Adam', 'Ben'], 1000);
});
}
async function findStudent(who) {
const list = await getStudentList();
const found = list.some(student => student === who);
console.log(found);
}
findStudent('Adam');
in above code, const list = getStudentList(); and const list = await getStudentList(); both functions like synchronous code.
Thank you
A synchronous function/code is a code that gets executed line by line, task by task. No matter how much time a specific task takes to be executed the next one doesn't start until the current one is finished, in other words the execution flow is paused/stopped in each task and starts back again when the current task is finished. i.e:
console.log("foo");
console.log("bar");
// executing this code will log the following:
// foo
// bar
An asynchronous function/call is a code that starts executed at a certain point in time and then the next tasks get executed even if the first one is not finished. So it gets executed in, say, a parallel timeline or thread if you want to call it.
An example of this would be having a function that logs "ASYNC" after 3 seconds (suppose we have a pre-defined delay function called sleep(seconds)):
async function foo() {
sleep(3); // wait for 3 seconds
console.log("ASYNC");
}
console.log("foo");
foo();
console.log("bar");
// executing this code will log the following:
// foo
// bar
// ASYNC
Note that bar was logged before ASYNC even though the function that logs the latter was called first. Basically asynchronous function don't stop the execution flow and just start executing the code inside it and goes on to the next line of code after the call, regardless of whether the async code was finished or not.
There are times when you actually want the execution flow to stop in asynchronous code. Say you have a variable called x and you want to have a sum operation function called calculate() and its result is stored to x but the function is an online request that is executed with a certain amount of delay (for example, 1 second).
let x = 0;
async main() {
console.log(x);
x = calculate(5,8);
console.log(x);
}
main();
// executing this code will log the following:
// 0
// {}
Note that the value of x didn't become 13 as expected but we got some weird result instead. This is because the request started executing and then the value of x was logged before the request has returned the sum, as a result (and depending on how a the request works) the value of x will be some random object or null/undefined until the request is finished and then x will be equal to 13
To fix this, we have to use the keyword await that stops the asynchronous execution flow and waits for another asynchronous function to end until the flow is back on.
let x = 0;
async main() {
console.log(x);
x = await calculate(5,8);
console.log(x);
}
main();
// executing this code will log the following with a 1 second delay between each log:
// 0
// 13
Side note: the await keyword cannot be used in synchronous context like
await someAsyncFunction();
and is only used before asynchronous functions (the ones that are defined with the async keyword).So await is only used with asynchronous functions in asynchronous contexts like this:
async someAsyncFunction() {
// some tasks
await anotherAsyncFunction();
// some more tasks
}
Your first example is synchronous. It's also faster.
function getStudentList(){
return ['Adam', 'Ben'];
}
function findStudent(who){
const list = getStudentList(), found = list.includes(who);
console.log(found); // logs true
}
console.time('sync'); findStudent('Adam'); console.timeEnd('sync');
Your second example is asynchronous, and slower by about a second. But, you wouldn't be able to test that, unless your async function is resolved first. That's why I used .then.
function getStudentList(){
return new Promise(resolve=>{
setTimeout(() => resolve(['Adam', 'Ben']), 1000);
});
}
async function findStudent(who){
const list = await getStudentList(), found = list.includes(who);
console.log(found);
}
console.time('async');
findStudent('Adam').then(()=>{
console.timeEnd('async');
});
You will notice that arrayInstance.includes is a better solution to find if something is in an Array. By the way, it makes no sense to use async in this particular case.
Here is an async example that makes more sense:
function delay(milliseconds){
return new Promise(resolve=>{
setTimeout(()=>{
resolve(milliseconds);
}, milliseconds);
});
}
async function logicalAsync(){
let wait;
console.time('test');
wait = await delay(1000);
console.timeEnd('test');
console.log('milliseconds = '+wait);
}
logicalAsync();
Of course, synchronous code takes however long it takes to execute, with all the code below it waiting on the above code to be finished processing. Asynchronous code allows the code below to execute (possibly) before the code above it is finished.
This question already has answers here:
stop settimeout in recursive function
(7 answers)
Javascript delete a function
(3 answers)
Closed 2 years ago.
const resumeInfinity = () => {
window.speechSynthesis.resume();
const timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
console.log(timeoutResumeInfinity);
}
utterThis.onstart = () => {
resumeInfinity();
};
need the (resumeInfinity) function to stop working after the speechSynthesi
To avoid error messages that resumeInfinity is not a function you shouldn't delete it but set it to an empty function. But as you set defined resumeInfinity as const you can't change that function.
So what you can do is to either change it to:
let resumeInfinity = () => {
// ... your code
}
And then do change it later to an empty function resumeInfinity = () => {}
But you need to keep in mind that if that original function was passed as callback earlier to somewhere else (e.g. like here setTimeout(resumeInfinity, 1000)) that this callback will still refer to the old function.
So a better solution would be to check if the function should still valid to be executed and do an early out otherwise.
const resumeInfinity = () => {
if( /* some check if isn't valid to call that function anymore */ ) {
return
}
window.speechSynthesis.resume();
const timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
console.log(timeoutResumeInfinity);
}
But all of these above solutions are in fact just a workaround, because if the logic of your application is correct then such a situation should never happen. So the need to do something like this indicates that you more likely need to think about restructuring your code.
If it is just about stopping the timeout then you need to call clearTimeout(timeoutResumeInfinity), and make timeoutResumeInfinity available at the place at which you know that the speechSynthesi finished.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I have a chrome extension. Its code has a method getSelectionFromPage() which catches the text selected on the webpage and always returns true like below:
function getSelectionFromPage() {
window.selected = true;
chrome.tabs.executeScript({
code: "window.getSelection().toString();"
}, function(selection) {
if (selection[0] != '') {
window.selected = true;
}else{
window.selected = false;
}
});
return true
}
On the same window context, I ran the following commands on the console.
The result can be seen as follows:
I am writing the same commands here also:
getSelectionFromPage() //-> true
window.selected //-> false
(getSelectionFromPage() && window.selected) //-> true
The (getSelectionFromPage() && window.selected) should be false. I have tried checking typeof(window.selected) and typeof(getSelectionFromPage()) and both are returning boolean. I don't understand why it is happening.
The function which is setting to false is a callback. This will not execute until after the current execution context is complete. Therefore, it will not be set to false until after && window.selection completes execution.
executeScript docs: https://developer.chrome.com/extensions/tabs#method-executeScript
The order of things is:
(function () {
window.selected = true; // Runs
chrome.tabs.executeScript({code: "window.getSelection().toString();"}, function(){
window.selected = false;
}); // Calls browser API and set's callback (the anonymous function there) to call later)
// NOTE: the callback function which was set here was NOT executed yet it was only defined.
return true;
})() // true
&& window.selected // this is currently true
// Later, now callback executes
If you would like to wait, you could use a Promise instead.
function getSelectionFromPage() {
return new Promise(function (resolve) {
chrome.tabs.executeScript(
{code: "window.getSelection().toString();"},
// or just put resolve here instead of defining a function to get value directly
function(v){
resolve(!!v);
}
);
});
}
getSelectionFromPage().then(haveSelection => console.log(haveSelection);
How to print some literal in console with console.log (or another command) command in same line?
For example:
print 1;
print 2;
print 3;
Console output: 123
Assuming I understood you correctly, you want a JavaScript equivalent of C#'s Console.Write, that appends (a) character(s) to the last line.
That's not possible.
The moment something is logged to the console, you no longer have access to it. You can't "append" to a logged line, you can't change it.
That said, you could write a wrapper that sortof emulates this behavior:
let logTimeout; // Keep track of the pending timeout
let logArguments = []; // Keep track of the passed loggable arguments
function log(...args) {
if (logTimeout) {
logTimeout = clearTimeout(logTimeout); // Reset the timeout if it's pending.
}
logArguments = logArguments.concat(args); // Add the new arguments.
logTimeout = setTimeout(() => { // Log all arguments after a short delay.
console.log(...logArguments);
logArguments.length = 0;
});
}
log(1);
log(2);
log(3);
log("foo");
log("bar");
log({crazy: "stuff"});
setTimeout(() => {
log(4);
log(5);
log(6);
log("baz");
log("woo");
log([{crazier: "stuff"}]);
}, 500);
Just note that this logger is asynchronous. This means your code that calls log will run to completion before something is actually logged.