Running background task in node.js - javascript

How do we run background tasks in node.js? So that I can perform multiple requests in parallel and simultaneously without blocking the UI. Once a request completes, I can inform the user that the operation is complete and the result is ready. While one request is getting processed, the end user is free to perform other operations as well

Javascript is single-threaded, so your programs must be asynchronous. Javascript uses events (callbacks, timeouts) to orchestrate the running of many quick function invocations. Nodejs doesn't have a UI to block, but these quick functions can be blocked by a slow function. This asynchronous nature of Javascript applies to both nodejs and browser code.
I believe your question is about how to deal with operations taking a lot of time.
One approach is to break up those operations into a lot of chunks -- quick function calls -- and have each of them use setTimeout() to start the next one. It's hard to suggest how to do this without understanding your long running function. Here's a question and some answers on the topic. How to break up a long running function in javascript, but keep performance
Summarizing the answer you use this sort of code.
function (data, callbackWhenDone) {
let n = 0
const max = data.length;
const batchSize = 100;
try {
function doBatch () {
let i
for (var i = 0; i < batch && n < max; ++i, ++n) {
doComputation(data[n])
}
if (n < max) setTimeout(doBatch, 0)
else callbackWhenDone(null, data)
}
} catch (error) {
callbackWhenDone(error)
}
doBatch()
}
The setTimeout(fn,0) at the end of the batch starts the next batch by queuing up a timeout in Javascript's main loop. Other items in that queue get a chance to run. Each batch knows where to start because the doBatch() function updates n as it runs. When the whole lot finishes, it invokes the callback you passed in. The callback uses the typical nodejs pattern where the first parameter, if not null, is an error.
Another approach is to use Worker Threads. You can put your computation's Javascript code into a separate Javascript context and have it run. You'll need the knack of passing the data back and forth from the main nodejs process to the thread. Make sure you have a reliable debugger setup before you try this; it can be confusing.

Related

does microtask queue instructions have higher priority than root-level instructions? [duplicate]

I wrote a simple function that returns Promise so should be non-blocking (in my opinion). Unfortunately, the program looks like it stops waiting for the Promise to finish. I am not sure what can be wrong here.
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
})
}
console.log("before")
longRunningFunc(1000, 3).then((res) => {
console.log("Result: " + res)
})
console.log("after")
The output looks like expected:
before // delay before printing below lines
after
Result: 5000049900000
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
Wrapping code in a promise (like you've done) does not make it non-blocking. The Promise executor function (the callback you pass to new Promise(fn) is called synchronously and will block which is why you see the delay in getting output.
In fact, there is no way to create your own plain Javascript code (like what you have) that is non-blocking except putting it into a child process, using a WorkerThread, using some third party library that creates new threads of Javascript or using the new experimental node.js APIs for threads. Regular node.js runs your Javascript as blocking and single threaded, whether it's wrapped in a promise or not.
You can use things like setTimeout() to change "when" your code runs, but whenever it runs, it will still be blocking (once it starts executing nothing else can run until it's done). Asynchronous operations in the node.js library all use some form of underlying native code that allows them to be asynchronous (or they just use other node.js asynchronous APIs that themselves use native code implementations).
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
As I said above, wrapping things in promise executor function doesn't make them asynchronous. If you want to "shift" the timing of when things run (thought they are still synchronous), you can use a setTimeout(), but that's not really making anything non-blocking, it just makes it run later (still blocking when it runs).
So, you could do this:
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
setTimeout(() => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
}, 10);
})
}
That would reschedule the time consuming for loop to run later and might "appear" to be non-blocking, but it actually still blocks - it just runs later. To make it truly non-blocking, you'd have to use one of the techniques mentioned earlier to get it out of the main Javascript thread.
Ways to create actual non-blocking code in node.js:
Run it in a separate child process and get an asynchronous notification when it's done.
Use the new experimental Worker Threads in node.js v11
Write your own native code add-on to node.js and use libuv threads or OS level threads in your implementation (or other OS level asynchronous tools).
Build on top of previously existing asynchronous APIs and have none of your own code that takes very long in the main thread.
The executor function of a promise is run synchronously, and this is why your code blocks the main thread of execution.
In order to not block the main thread of execution, you need to periodically and cooperatively yield control while the long running task is performed. In effect, you need to split the task into subtasks, and then coordinate the running of subtasks on new ticks of the event loop. In this way you give other tasks (like rendering and responding to user input) the opportunity to run.
You can either write your own async loop using the promise API, or you can use an async function. Async functions enable the suspension and resumation of functions (reentrancy) and hide most of the complexity from you.
The following code uses setTimeout to move subtasks onto new event loop ticks. Of course, this could be generalised, and batching could be used to find a balance between progress through the task and UI responsiveness; the batch size in this solution is only 1, and so progress is slow.
Finally: the real solution to this kind of problem is probably a Worker.
const $ = document.querySelector.bind(document)
const BIG_NUMBER = 1000
let count = 0
// Note that this could also use requestIdleCallback or requestAnimationFrame
const tick = (fn) => new Promise((resolve) => setTimeout(() => resolve(fn), 5))
async function longRunningTask(){
while (count++ < BIG_NUMBER) await tick()
console.log(`A big number of loops done.`)
}
console.log(`*** STARTING ***`)
longRunningTask().then(() => console.log(`*** COMPLETED ***`))
$('button').onclick = () => $('#output').innerHTML += `Current count is: ${count}<br/>`
* {
font-size: 16pt;
color: gray;
padding: 15px;
}
<button>Click me to see that the UI is still responsive.</button>
<div id="output"></div>

When Promises block execution [duplicate]

I wrote a simple function that returns Promise so should be non-blocking (in my opinion). Unfortunately, the program looks like it stops waiting for the Promise to finish. I am not sure what can be wrong here.
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
})
}
console.log("before")
longRunningFunc(1000, 3).then((res) => {
console.log("Result: " + res)
})
console.log("after")
The output looks like expected:
before // delay before printing below lines
after
Result: 5000049900000
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
Wrapping code in a promise (like you've done) does not make it non-blocking. The Promise executor function (the callback you pass to new Promise(fn) is called synchronously and will block which is why you see the delay in getting output.
In fact, there is no way to create your own plain Javascript code (like what you have) that is non-blocking except putting it into a child process, using a WorkerThread, using some third party library that creates new threads of Javascript or using the new experimental node.js APIs for threads. Regular node.js runs your Javascript as blocking and single threaded, whether it's wrapped in a promise or not.
You can use things like setTimeout() to change "when" your code runs, but whenever it runs, it will still be blocking (once it starts executing nothing else can run until it's done). Asynchronous operations in the node.js library all use some form of underlying native code that allows them to be asynchronous (or they just use other node.js asynchronous APIs that themselves use native code implementations).
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
As I said above, wrapping things in promise executor function doesn't make them asynchronous. If you want to "shift" the timing of when things run (thought they are still synchronous), you can use a setTimeout(), but that's not really making anything non-blocking, it just makes it run later (still blocking when it runs).
So, you could do this:
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
setTimeout(() => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
}, 10);
})
}
That would reschedule the time consuming for loop to run later and might "appear" to be non-blocking, but it actually still blocks - it just runs later. To make it truly non-blocking, you'd have to use one of the techniques mentioned earlier to get it out of the main Javascript thread.
Ways to create actual non-blocking code in node.js:
Run it in a separate child process and get an asynchronous notification when it's done.
Use the new experimental Worker Threads in node.js v11
Write your own native code add-on to node.js and use libuv threads or OS level threads in your implementation (or other OS level asynchronous tools).
Build on top of previously existing asynchronous APIs and have none of your own code that takes very long in the main thread.
The executor function of a promise is run synchronously, and this is why your code blocks the main thread of execution.
In order to not block the main thread of execution, you need to periodically and cooperatively yield control while the long running task is performed. In effect, you need to split the task into subtasks, and then coordinate the running of subtasks on new ticks of the event loop. In this way you give other tasks (like rendering and responding to user input) the opportunity to run.
You can either write your own async loop using the promise API, or you can use an async function. Async functions enable the suspension and resumation of functions (reentrancy) and hide most of the complexity from you.
The following code uses setTimeout to move subtasks onto new event loop ticks. Of course, this could be generalised, and batching could be used to find a balance between progress through the task and UI responsiveness; the batch size in this solution is only 1, and so progress is slow.
Finally: the real solution to this kind of problem is probably a Worker.
const $ = document.querySelector.bind(document)
const BIG_NUMBER = 1000
let count = 0
// Note that this could also use requestIdleCallback or requestAnimationFrame
const tick = (fn) => new Promise((resolve) => setTimeout(() => resolve(fn), 5))
async function longRunningTask(){
while (count++ < BIG_NUMBER) await tick()
console.log(`A big number of loops done.`)
}
console.log(`*** STARTING ***`)
longRunningTask().then(() => console.log(`*** COMPLETED ***`))
$('button').onclick = () => $('#output').innerHTML += `Current count is: ${count}<br/>`
* {
font-size: 16pt;
color: gray;
padding: 15px;
}
<button>Click me to see that the UI is still responsive.</button>
<div id="output"></div>

Promise.Resolve is blocking UI [duplicate]

I wrote a simple function that returns Promise so should be non-blocking (in my opinion). Unfortunately, the program looks like it stops waiting for the Promise to finish. I am not sure what can be wrong here.
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
})
}
console.log("before")
longRunningFunc(1000, 3).then((res) => {
console.log("Result: " + res)
})
console.log("after")
The output looks like expected:
before // delay before printing below lines
after
Result: 5000049900000
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
Wrapping code in a promise (like you've done) does not make it non-blocking. The Promise executor function (the callback you pass to new Promise(fn) is called synchronously and will block which is why you see the delay in getting output.
In fact, there is no way to create your own plain Javascript code (like what you have) that is non-blocking except putting it into a child process, using a WorkerThread, using some third party library that creates new threads of Javascript or using the new experimental node.js APIs for threads. Regular node.js runs your Javascript as blocking and single threaded, whether it's wrapped in a promise or not.
You can use things like setTimeout() to change "when" your code runs, but whenever it runs, it will still be blocking (once it starts executing nothing else can run until it's done). Asynchronous operations in the node.js library all use some form of underlying native code that allows them to be asynchronous (or they just use other node.js asynchronous APIs that themselves use native code implementations).
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
As I said above, wrapping things in promise executor function doesn't make them asynchronous. If you want to "shift" the timing of when things run (thought they are still synchronous), you can use a setTimeout(), but that's not really making anything non-blocking, it just makes it run later (still blocking when it runs).
So, you could do this:
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
setTimeout(() => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
}, 10);
})
}
That would reschedule the time consuming for loop to run later and might "appear" to be non-blocking, but it actually still blocks - it just runs later. To make it truly non-blocking, you'd have to use one of the techniques mentioned earlier to get it out of the main Javascript thread.
Ways to create actual non-blocking code in node.js:
Run it in a separate child process and get an asynchronous notification when it's done.
Use the new experimental Worker Threads in node.js v11
Write your own native code add-on to node.js and use libuv threads or OS level threads in your implementation (or other OS level asynchronous tools).
Build on top of previously existing asynchronous APIs and have none of your own code that takes very long in the main thread.
The executor function of a promise is run synchronously, and this is why your code blocks the main thread of execution.
In order to not block the main thread of execution, you need to periodically and cooperatively yield control while the long running task is performed. In effect, you need to split the task into subtasks, and then coordinate the running of subtasks on new ticks of the event loop. In this way you give other tasks (like rendering and responding to user input) the opportunity to run.
You can either write your own async loop using the promise API, or you can use an async function. Async functions enable the suspension and resumation of functions (reentrancy) and hide most of the complexity from you.
The following code uses setTimeout to move subtasks onto new event loop ticks. Of course, this could be generalised, and batching could be used to find a balance between progress through the task and UI responsiveness; the batch size in this solution is only 1, and so progress is slow.
Finally: the real solution to this kind of problem is probably a Worker.
const $ = document.querySelector.bind(document)
const BIG_NUMBER = 1000
let count = 0
// Note that this could also use requestIdleCallback or requestAnimationFrame
const tick = (fn) => new Promise((resolve) => setTimeout(() => resolve(fn), 5))
async function longRunningTask(){
while (count++ < BIG_NUMBER) await tick()
console.log(`A big number of loops done.`)
}
console.log(`*** STARTING ***`)
longRunningTask().then(() => console.log(`*** COMPLETED ***`))
$('button').onclick = () => $('#output').innerHTML += `Current count is: ${count}<br/>`
* {
font-size: 16pt;
color: gray;
padding: 15px;
}
<button>Click me to see that the UI is still responsive.</button>
<div id="output"></div>

Promise control flow [duplicate]

I wrote a simple function that returns Promise so should be non-blocking (in my opinion). Unfortunately, the program looks like it stops waiting for the Promise to finish. I am not sure what can be wrong here.
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
})
}
console.log("before")
longRunningFunc(1000, 3).then((res) => {
console.log("Result: " + res)
})
console.log("after")
The output looks like expected:
before // delay before printing below lines
after
Result: 5000049900000
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
Wrapping code in a promise (like you've done) does not make it non-blocking. The Promise executor function (the callback you pass to new Promise(fn) is called synchronously and will block which is why you see the delay in getting output.
In fact, there is no way to create your own plain Javascript code (like what you have) that is non-blocking except putting it into a child process, using a WorkerThread, using some third party library that creates new threads of Javascript or using the new experimental node.js APIs for threads. Regular node.js runs your Javascript as blocking and single threaded, whether it's wrapped in a promise or not.
You can use things like setTimeout() to change "when" your code runs, but whenever it runs, it will still be blocking (once it starts executing nothing else can run until it's done). Asynchronous operations in the node.js library all use some form of underlying native code that allows them to be asynchronous (or they just use other node.js asynchronous APIs that themselves use native code implementations).
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
As I said above, wrapping things in promise executor function doesn't make them asynchronous. If you want to "shift" the timing of when things run (thought they are still synchronous), you can use a setTimeout(), but that's not really making anything non-blocking, it just makes it run later (still blocking when it runs).
So, you could do this:
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
setTimeout(() => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
}, 10);
})
}
That would reschedule the time consuming for loop to run later and might "appear" to be non-blocking, but it actually still blocks - it just runs later. To make it truly non-blocking, you'd have to use one of the techniques mentioned earlier to get it out of the main Javascript thread.
Ways to create actual non-blocking code in node.js:
Run it in a separate child process and get an asynchronous notification when it's done.
Use the new experimental Worker Threads in node.js v11
Write your own native code add-on to node.js and use libuv threads or OS level threads in your implementation (or other OS level asynchronous tools).
Build on top of previously existing asynchronous APIs and have none of your own code that takes very long in the main thread.
The executor function of a promise is run synchronously, and this is why your code blocks the main thread of execution.
In order to not block the main thread of execution, you need to periodically and cooperatively yield control while the long running task is performed. In effect, you need to split the task into subtasks, and then coordinate the running of subtasks on new ticks of the event loop. In this way you give other tasks (like rendering and responding to user input) the opportunity to run.
You can either write your own async loop using the promise API, or you can use an async function. Async functions enable the suspension and resumation of functions (reentrancy) and hide most of the complexity from you.
The following code uses setTimeout to move subtasks onto new event loop ticks. Of course, this could be generalised, and batching could be used to find a balance between progress through the task and UI responsiveness; the batch size in this solution is only 1, and so progress is slow.
Finally: the real solution to this kind of problem is probably a Worker.
const $ = document.querySelector.bind(document)
const BIG_NUMBER = 1000
let count = 0
// Note that this could also use requestIdleCallback or requestAnimationFrame
const tick = (fn) => new Promise((resolve) => setTimeout(() => resolve(fn), 5))
async function longRunningTask(){
while (count++ < BIG_NUMBER) await tick()
console.log(`A big number of loops done.`)
}
console.log(`*** STARTING ***`)
longRunningTask().then(() => console.log(`*** COMPLETED ***`))
$('button').onclick = () => $('#output').innerHTML += `Current count is: ${count}<br/>`
* {
font-size: 16pt;
color: gray;
padding: 15px;
}
<button>Click me to see that the UI is still responsive.</button>
<div id="output"></div>

Javascript async array manipulation blocks UI [duplicate]

I wrote a simple function that returns Promise so should be non-blocking (in my opinion). Unfortunately, the program looks like it stops waiting for the Promise to finish. I am not sure what can be wrong here.
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
})
}
console.log("before")
longRunningFunc(1000, 3).then((res) => {
console.log("Result: " + res)
})
console.log("after")
The output looks like expected:
before // delay before printing below lines
after
Result: 5000049900000
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
Wrapping code in a promise (like you've done) does not make it non-blocking. The Promise executor function (the callback you pass to new Promise(fn) is called synchronously and will block which is why you see the delay in getting output.
In fact, there is no way to create your own plain Javascript code (like what you have) that is non-blocking except putting it into a child process, using a WorkerThread, using some third party library that creates new threads of Javascript or using the new experimental node.js APIs for threads. Regular node.js runs your Javascript as blocking and single threaded, whether it's wrapped in a promise or not.
You can use things like setTimeout() to change "when" your code runs, but whenever it runs, it will still be blocking (once it starts executing nothing else can run until it's done). Asynchronous operations in the node.js library all use some form of underlying native code that allows them to be asynchronous (or they just use other node.js asynchronous APIs that themselves use native code implementations).
But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?
As I said above, wrapping things in promise executor function doesn't make them asynchronous. If you want to "shift" the timing of when things run (thought they are still synchronous), you can use a setTimeout(), but that's not really making anything non-blocking, it just makes it run later (still blocking when it runs).
So, you could do this:
function longRunningFunc(val, mod) {
return new Promise((resolve, reject) => {
setTimeout(() => {
sum = 0;
for (var i = 0; i < 100000; i++) {
for (var j = 0; j < val; j++) {
sum += i + j % mod
}
}
resolve(sum)
}, 10);
})
}
That would reschedule the time consuming for loop to run later and might "appear" to be non-blocking, but it actually still blocks - it just runs later. To make it truly non-blocking, you'd have to use one of the techniques mentioned earlier to get it out of the main Javascript thread.
Ways to create actual non-blocking code in node.js:
Run it in a separate child process and get an asynchronous notification when it's done.
Use the new experimental Worker Threads in node.js v11
Write your own native code add-on to node.js and use libuv threads or OS level threads in your implementation (or other OS level asynchronous tools).
Build on top of previously existing asynchronous APIs and have none of your own code that takes very long in the main thread.
The executor function of a promise is run synchronously, and this is why your code blocks the main thread of execution.
In order to not block the main thread of execution, you need to periodically and cooperatively yield control while the long running task is performed. In effect, you need to split the task into subtasks, and then coordinate the running of subtasks on new ticks of the event loop. In this way you give other tasks (like rendering and responding to user input) the opportunity to run.
You can either write your own async loop using the promise API, or you can use an async function. Async functions enable the suspension and resumation of functions (reentrancy) and hide most of the complexity from you.
The following code uses setTimeout to move subtasks onto new event loop ticks. Of course, this could be generalised, and batching could be used to find a balance between progress through the task and UI responsiveness; the batch size in this solution is only 1, and so progress is slow.
Finally: the real solution to this kind of problem is probably a Worker.
const $ = document.querySelector.bind(document)
const BIG_NUMBER = 1000
let count = 0
// Note that this could also use requestIdleCallback or requestAnimationFrame
const tick = (fn) => new Promise((resolve) => setTimeout(() => resolve(fn), 5))
async function longRunningTask(){
while (count++ < BIG_NUMBER) await tick()
console.log(`A big number of loops done.`)
}
console.log(`*** STARTING ***`)
longRunningTask().then(() => console.log(`*** COMPLETED ***`))
$('button').onclick = () => $('#output').innerHTML += `Current count is: ${count}<br/>`
* {
font-size: 16pt;
color: gray;
padding: 15px;
}
<button>Click me to see that the UI is still responsive.</button>
<div id="output"></div>

Categories