How can i use long callback in javascript? [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I want to make some kind of crawling program. it's chrome extension.
In my program, one function is visit many webpage. This is my plan.
visit page, load page, crawling, visit next page....
I want my program is sequential. but, 'load page' is async. therfore, lower code is not work.
function load_and_download(checked_list) {
for(var item of checked_list){
visit_page(item); //async function
crawl_page(item);
}
}
I found solution like this.
function load_and_download(checked_list, now_index) {
visit_page(checked_list[now_index], function () {//load finish
crawl_page(checked_list[now_index]);
if (checked_list.length > now_index + 1)
load_and_download(checked_list, now_index+1);
})
}
upper code work for me. but, it is recursive function.
if checked_list is very very long, upper code is safe? I know recursive code has stack problem. javascript is safe from that?

What you have here is not a recursive function, if visit_page calls back asynchronously. This pattern is something which I'd like to call pseudorecursion, as due to the async callback, every call to load_and_download will happen in a separate task, thus inside the callstack there will be only one call to that function (per task). Once the async action is scheduled in visit_page, the callstack unwinds again and the next task will be processed. Therefore although it looks like recursion, there's actually no recursion going on.
Here's a simplified example illustrating this:
function asynchronous(callback) {
// Here an asynchronous action gets started and processed somewhere
setTimeout(callback, 1000);
// Execution continues synchronously and the callstack unwinds from here on
}
function pseudoRecursive() {
asynchronous(function () {
console.log("As we're in a new task, the callstack is basically empty:\n", (new Error()).stack);
pseudoRecursive();
});
// Here the callstack unwinds again
}
pseudoRecursive();

Related

Why requestAniamtionFrame doesn't cause stack overflow error?

I am trying to understand what happens under the hood of the browser when requestAnimationFrame() is called recursively.
I have ran code like this in my browser console:
function foo(){
requestAnimationFrame(foo);
console.log("foo");
}
foo()
The result: "foo" is being printend out non-stop.
My problem: I cannot figure out how I am not exceeding allowed stack size.
What I think is happening:
function callAsynchronously(callback){
setTimeout(callback, 1);
}
function foobar(){
callAsynchronously(foobar); // replacement for requestAnimationFrame
console.log("hi");
}
foobar() // result is the same as before, non-stop printing
Above code is how I am visualizing requestAnimationFrame:
foobar() is put on the stack
callAsynchronously(foobar) is put on stack
callAsynchronously(foobar) popped from the stack
console.log("hi") is put on stack / browser apis put foobar callback into some queue after setTimeout is finished
console.log("hi") is popped from the stack
browser sees empty stack and puts callback from the queue on the stack
Repeat
I assume that requestAnimationFrame does something similar to not exceed allowed stack size but I am not sure if that's all there is to it. Also does it mean that I can bombard browser apis with async callbacks without getting any errors as long as I keep my stack size within acceptable range?
requestAnimationFrame doesn't run until all synchronous execution has completed. It schedules the given callback. It acts very much like setTimeout. Its not truly recursive, it just seems that way. Thats the nature of the event loop.
requestAnimationFrame is called according to the refresh rate of the device screen. For example if you are viewing on 60hz screen the foo function will be called 60 times.

The difference between using setTimeout(fn, 0) and not using it [duplicate]

This question already has answers here:
Why is setTimeout(fn, 0) sometimes useful?
(19 answers)
Closed 3 years ago.
I have a simple question about setTimeout function
My function:
function myFunc(){
// some code here
}
What's different when
I call a function with and without setTimeout:
myFunc();
setTimeout(function(){
myFunc();
}, 0);
Can someone explain help me? Thank you.
setTimeout waits for a given delay then schedules a new task for its callback. This is why setTimeout is logged after script end, as logging script end is part of the first task, and setTimeout is logged in a separate task. Right, we're almost through this, but I need you to stay strong for this next bitā€¦
Tasks are scheduled so the browser can get from its internals into JavaScript/DOM land and ensures these actions happen sequentially. Between tasks, the browser may render updates. Getting from a mouse click to an event callback requires scheduling a task, as does parsing HTML, and in the above example, setTimeout.
https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
setTimeout(,0) will call after all current queue will be finished, and
normal function call goes in the queue first.
You can see here:
function myFunc1(){
console.log("In myFunc1");
}
function myFunc2(){
console.log("In myFunc2");
}
setTimeout(function(){
myFunc1();
}, 0);
myFunc2();

Any drawbacks of having all functions async? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
The newer node js has async await, which are really cool because it makes the code look better.
I was wondering if it's a good idea to make every class method async, even if it doesn't need to return a promise?
In my use case I actually sort of need that because I'm trying to share dependencies between multiple child processes, and I'm using a combination of Proxy and child process communication to achieve this. And obviously I need promises because I need to wait for the processes to respond or send messages.
But does this have any potential side effects, maybe in the long term?
To be more clear, I want to do this solely for the benefit of cool syntax.
const database = CreateProxy('database');
await database.something();
From another process.
versus some code that just requests something from the parent process like
process.send('getSomethingFromDb');
Under the hood both use messaging, but the first one makes it look like it doesn't on the surface
This concept is a subject for Occam's razor. There are no benefits, while there may be disadvantages.
Extra overhead (both CPU and time) is one of the problems. Promises take some time and resources to be resolved. This may take much less than a millisecond, yet a lag can accumulate.
Another problem is that asynchronicity is contagious, once it reaches module scope, async IIFE should be used everywhere - because top-level await isn't supported yet:
module.export = (async () => {
await require('foo');
// await was accidentally dropped
// this results in race condition and incorrect error handling
require('foo');
...
})();
And here's a good example of a disadvantage that complicates error handling:
async function foo() {
throw new Error('foo');
}
async function bar() {
try {
return foo();
} catch (err) {
console.log('caught with bar');
}
}
bar(); // UnhandledPromiseRejectionWarning: Error: foo
Despite control flow looks synchrounous-like in async, errors are handled differently. foo returns rejected promise, and returned values aren't handled with try..catch in async functions. A rejection won't be handled in bar.
This wouldn't happen with regular function:
function foo() {
throw new Error('foo');
}
function bar() {
try {
return foo();
} catch (err) {
console.log('caught with bar');
}
}
bar(); // caught with bar
Things may become more complicated with third-party libraries that were designed to work synchronously.
I was wondering if it's a good idea to make every class method async,
even if it doesn't need to return a promise?
Your code will work, but I would not recommand it for two reason :
Unnecessary memory/cpu usage
It will makes your code hard to understand. Knowing which function is asynchronous or synchronous is important to understand how a system work and what it is doing.
The result of calling an async function will always be a Promise, regardless of if the function implements any asynchronous behavior.
const asyncTest = async () => 3;
console.log(asyncTest()); // logs 'PromiseĀ {<resolved>: 3}'
Because of that, you have to always be sure to call such function with await. But that is purely a comfort issue, if even that for you. But also, creating and resolving Promises adds a little bit of time to each function call, so if performance is critical, you should avoid to call async functions in large numbers, if it can be avoided.

Making a namepaced function asynchronous using setimeout [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have this function which is using namespace. I want to make it asynchronous. Assuming that this function is being called on click of some button ?
var ns = {
somemfunc: function (data) {
alert("hello");
}
}
EDIT - Sorry for being unclear on this. I want to make the call to this function asynchronous by putting the settimeout function inside the somefunc function. Not sure how to do that.
Thanks in advance
You can set this function to be called asynchronously by adding a setTimeout block within the definition of somefunc, note that I am using the term asynchronous loosely here as this function isn't really doing any asynchronous work. An async function would be a function that does some work that takes some time to execute, such as making a network request, aggregating its results and then reporting back to the caller to do some sort of DOM refresh or something, it normally reports back to the caller using a callback, or resolving/rejecting a promise, in the time that this long running code is running, the Event Queue is not blocked and can continue to process other actions if this was not the case then the app would be unresponsive until the long running task finished computing.
What you want to achieve here is not truly async as you're simply scheduling the function to run on the Event Queue in 2 seconds.
var ns = {
somemfunc: function (data) {
setTimeout(function() {
alert("hello");
}, 2000);
}
}
ns.somemfunc();
When ns.somefunc() is called, its now set to execute the function somefunc on the Event Queue in 2000ms (2 seconds). Remember Javascript is single threaded, tasks are scheduled to run on the event queue and will be processed contiguously. If you set the timeout to run the function after 2000ms but the jobs before it take 500ms to compute, then we actually wait 2500ms for the queue to serve that function.

How can I queue and execute multiple promises asynchronously with a single callback? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am using the http request library got. With this package, http connections are asynchronous, fast, and easy to type out. The "got"cha is that got is a promisified package, which brings up several challenges for me. One is that I don't know how to pass around a reference to the got.
What I need to do is use got together with file streams to download the page contents of several url's. Upon completion of all of these streams, I want to continue in the code.
In this example instead of making an array of promises I am getting an array of response objects.
const getFile = (fileUrl) => {
return new Promise((resolve) => {
got.stream(fileUrl).pipe(fs.createWriteStream(path.basename(fileUrl)))
.on('finish', () => {
successMessage('downloaded ' + fileUrl + '!');
resolve();
});
});
};
// create an array of these got promises
let promises = []
for (let file of body.files) {
promises.push(getFile(file));
}
The reason the getFile helper exists is to wrap the got in a promise so that after performing all of the gots, I can use a promise.all call:
// after all got's have executed
promises.all(promises).then(() => {
console.log('all promises resolved');
}
Looking for assistance understanding how to change the first snippet so that promises.all behaves as anticipated.
The Promise aggregation function is called Promise.all() not promises.all().

Categories

Resources