Button click event image hiding is delayed

  • Context: JavaScript 
  • Thread starter Thread starter Bob Walance
  • Start date Start date
  • Tags Tags
    Html Image Javascript
Click For Summary

Discussion Overview

The discussion revolves around a problem with a button click event in a webpage project where an image is not hiding immediately as intended. Participants explore the implications of using a sleep function in JavaScript and its effect on the browser's display updates. The conversation includes technical explanations, proposed solutions, and challenges related to asynchronous programming in JavaScript.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant describes an issue where an image does not hide immediately upon a button click due to the presence of a sleep function that delays execution.
  • Another participant questions the necessity of the sleep function, suggesting it may not be needed for the intended functionality.
  • A participant explains that JavaScript does not update the browser display until after an event handler returns, which complicates the use of time delays in event handlers.
  • There is mention of an unreliable event-driven mechanism for audio playback that the participant is attempting to use, which may be contributing to the issue.
  • Some participants discuss alternatives to the sleep function, such as using setTimeout to allow the browser to update the display while waiting.
  • One participant shares a potential solution involving an async function and a custom sleep implementation using Promises.
  • Another participant expresses skepticism about the effectiveness of the tone.js module for their specific musical requirements.

Areas of Agreement / Disagreement

Participants do not reach a consensus on the best approach to resolve the issue. There are multiple competing views regarding the use of the sleep function and the best practices for handling asynchronous behavior in JavaScript.

Contextual Notes

Participants note that JavaScript's single-threaded nature can lead to issues when blocking operations are used, which may cause the browser to become unresponsive. The discussion highlights the need for a shift in mindset when transitioning from synchronous to asynchronous programming.

Who May Find This Useful

This discussion may be useful for web developers dealing with event handling and asynchronous programming in JavaScript, particularly those transitioning from other programming languages.

Bob Walance
Insights Author
Gold Member
Messages
84
Reaction score
55
TL;DR
The style.visibility = 'hidden' image attribute is not taking effect until end of sleep function
My webpage project has a button labeled 'Harmonics' with a mouse-click event. I want an image to be hidden as soon as the button is clicked, however this doesn't happen.

Here's a snippet of the html. It doesn't matter what order the two Javascript functions are called. The 'hidden' attribute for the image does not take effect until the sleep function completes.

gwd.Harmonics = function(event) {
document.getElementsByClassName('gwd-img-17a0')[0].style.visibility = 'hidden'; // hide the image
sleep(2000); // delay for 2000ms

Can anyone tell me if this can be fixed so that the image is hidden as soon as the button is clicked?
 
Technology news on Phys.org
PeterDonis said:
Why is the sleep function there at all?
I'm just using a sleep function here to simply demonstrate the issue. The real project is playing a tone and I need to know when the tone has ended. There is an event-driven mechanism for this but it is unreliable so I'm using a simple date/time-based timer in order to know when to start the next tone.
 
Bob Walance said:
I'm just using a sleep function here to simply demonstrate the issue.
Unfortunately, the issue you are running up against, at least as I understand how the Javascript engine works, is simple: your function is an event handler and Javascript doesn't update the browser display to reflect any changes the event handler makes until after the handler returns. So you can't put any kind of time delay tracking mechanism in an event handler because it delays updating the browser display.

Bob Walance said:
There is an event-driven mechanism for this but it is unreliable
How so?
 
PeterDonis said:
Unfortunately, the issue you are running up against, at least as I understand how the Javascript engine works, is simple: your function is an event handler and Javascript doesn't update the browser display to reflect any changes the event handler makes until after the handler returns. So you can't put any kind of time delay tracking mechanism in an event handler because it delays updating the browser display.
PeterDonis said:
How so?
1 - I was afraid of that. That's really how it appears to be behaving. Darn.
2 - I think that the audioContext tone generation 'onend' event issue is related to "Javascript doesn't update the browser display..." operation that you pointed out.

My app's purpose is to demonstrate the difference, musically, between equal-temperament tuning and simple harmonics of an instrument note (nature). The part of the app that plays one tone or chord works perfectly. When I need a sequence of tones (e.g. in a musical scale) then I run into these issues.

I have a complete application written and working in Python, but I can't distribute the Python code here. That's why I'm attempting to get it to work in a web browser.
 
Bob Walance said:
2 - I think that the audioContext tone generation 'onend' event issue is related to "Javascript doesn't update the browser display..." operation that you pointed out.
There is no AudioContext onend event. Perhaps you are thinking of the AudioScheduledSourceNode ended event: https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/ended_event

Bob Walance said:
My app's purpose is to demonstrate the difference, musically, between equal-temperament tuning and simple harmonics of an instrument note (nature). The part of the app that plays one tone or chord works perfectly. When I need a sequence of tones (e.g. in a musical scale) then I run into these issues.
Perhaps you might be better off using the tone.js module I showed you on another thread.

Bob Walance said:
I have a complete application written and working in Python, but I can't distribute the Python code here. That's why I'm attempting to get it to work in a web browser.
Programming for the web is very different from programming in Python, you need to completely change your mindset to write asynchronous, event driven code rather than the blocking code you are used to.
 
pbuk said:
There is no AudioContext onend event. Perhaps you are thinking of the AudioScheduledSourceNode ended event: https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/
Perhaps you might be better off using the tone.js module I showed you on another thread.

Programming for the web is very different from programming in Python, you need to completely change your mindset to write asynchronous, event driven code rather than the blocking code you are used to.

pbuk said:
There is no AudioContext onend event. Perhaps you are thinking of the AudioScheduledSourceNode ended event: https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/ended_eventPerhaps you might be better off using the tone.js module I showed you on another thread.Programming for the web is very different from programming in Python, you need to completely change your mindset to write asynchronous, event driven code rather than the blocking code you are used to.

I did look at tone.js but I don't think it'll do what I want. For example, I need to play two major chords:
A + C# + E
and
440Hz + 550Hz + 660Hz

They both sound close but the latter is much sweeter sounding. The beat frequency produced between the C# and the fifth harmonic of 110Hz is very obvious when it's juxtaposed with the natural major third interval.
 
jedishrfu said:
Maybe this will work:

https://www.codegrepper.com/code-ex...+to+reload+page+on+button+click+in+javascript

It's likely an ugly solution, but from it, you might find a better way.

Thanks. I'm aware of this and am utilizing it to make repeated musical scales more reliable (I'm not sure where the real issue is there).

I should have been a software engineer. Their life is SO much easier overall. They can just sit at their computers all day sipping their Daiquiris while us EEs have to go into the lab and inhale lead fumes.
 
  • #10
Sadly, you have a romanticized view of software engineers. Yes, we can code but a lot of time is spent tracking down your own or other people's misguided coding mistakes, and some can be downright impossible to find in a timely fashion.

So revel in the fact that you are a talented engineer learning the ropes of programming.
 
  • Like
Likes   Reactions: Bob Walance
  • #11
There is actually no sleep function in javascript. And if you keep javascript busy in a different fashion, all other activity is on hold as @PeterDonis already pointed out. Moreover, if you keep javascript busy for too long (a couple of seconds), the browser will complain that a script is causing trouble and ask if you want to kill it.

If you do want to sleep, then the relevant function is setTimeout, which takes a callback that will be called after a time. During this time all other activity resumes and the browser will display anything that was changed.

If you want to wait for it and continue what you were doing, then you can use:
Code:
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
gwd.Harmonics = async function(event) {
  document.getElementsByClassName('gwd-img-17a0')[0].style.visibility = 'hidden'; // hide the image
  await sleep(2000); // delay for 2000ms
  // Other processing
}
Note that the sleep is implemented using setTimeout, and all other activity will resume during this time so your element will immediately become invisible.
 
Last edited:
  • Love
Likes   Reactions: Bob Walance
  • #12
I like Serena said:
If you want to wait for it and continue what you were doing, then you can use:
Code:
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
gwd.Harmonics = async function(event) {
  document.getElementsByClassName('gwd-img-17a0')[0].style.visibility = 'hidden'; // hide the image
  await sleep(2000); // delay for 2000ms
  // Other processing
}
Note that the sleep is implemented using setTimeout, and all other activity will resume during this time so your element will immediately become invisible.
YES! Your solution works perfectly. I was just about to give up and try a different approach, but you completely solved my problem.

Thank you very much, liker of Serena.
 
  • Like
Likes   Reactions: I like Serena

Similar threads

  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 2 ·
Replies
2
Views
5K
  • · Replies 8 ·
Replies
8
Views
3K