-1

Spent time reading the answers here which helped me understand the asynchronous nature of JavaScript a little better. I'm still getting my feet wet. I'm trying to create my own callbacks by bindings setTimeouts to different events. Specifically change and click. I'm clearly missing something. When I select a year, I get below error in the console. Any help? Thanks!

html

<select id="select_year">
<option value="2021">2021</option>
<option value="2022">2022</option>
<option value="2023">2023</option>
</select>

js

function selectYear(selectedYear) {

$(document).on('change','#select_year',setTimeout(function() {

selectedYear = $(this).val();

}, 0),

)}


selectYear(function(year) {
console.log(year);
});

error in console

Uncaught TypeError: t.nodeName is undefined
    val jQuery
    selectYear http://localhost:8080/js/calendar.js:20
    setTimeout handler*selectYear http://localhost:8080/js/calendar.js:18
    <anonymous> http://localhost:8080/js/calendar.js:25
jquery.min.js:2:69132
    val jQuery
    selectYear http://localhost:8080/js/calendar.js:20
    (Async: setTimeout handler)
    selectYear http://localhost:8080/js/calendar.js:18
    <anonymous> http://localhost:8080/js/calendar.js:25
Grogu
  • 2,097
  • 15
  • 36
  • I think you need to do `$(document).on('change','#select_year',function() {var $this = ${this);setTimeout(function() {/* code - $this is the element */}, 0);});`, Plus - your argument to the function `selectYear` seems to be the year rather than a function callback, but it is used as both in a very piacular way. – Hagai Wild Jan 18 '21 at 19:12
  • It's really not clear why you're using `setTimeout` here. Could you clarify? – Jeff McMahan Jan 18 '21 at 19:23
  • @jeff_mcmahan: I'm not trying to call it inside the function. I need to pass the result to an external function to use the variable elsewhere in my codes. Inside the function this is easy. Now outside is the trick. – Grogu Jan 18 '21 at 19:33
  • @HagaiWild: sir, could you post a full answer? I think that's it – Grogu Jan 18 '21 at 19:34

2 Answers2

1

To do what you're doing here does not require a setTimeout. Event-driven programming is asynchronous by its nature to begin with. Try this:

'use strict'

const selectYear = year => {
  alert(year);
}

$('#select_year').on('change', function () {
    // This is your callback.
    let selectedYear = $(this).val();
    selectYear(selectedYear);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="select_year">
  <option value="2021">2021</option>
  <option value="2022">2022</option>
  <option value="2023">2023</option>
</select>
Jeff McMahan
  • 1,324
  • 12
  • 15
0

I'm clearly missing something.

True! And I would even say many things.

When talking about asynchrounous functions, we usually refer to function calls that resolve in a later time, not blocking the rest of a script execution. Look for promise if that is what you wish to understand.

What you do wrong in the provided code:

jQuery .on() is an event handler method. You can pass 3 arguments:

  • event (mandatory)
  • delegated selector (optionnal)
  • callback (mandatory)

In this case, the callback is a function that is getting executed when an event fires. That isn't the same as an asynchonous function. What is an event?

With your attempt, you did not pass a function expression or a function reference... but a function call. if you want a setTimeout to be exectuted when an event fires, you have to put it inside a function statement like below:

$(document).on('change','#select_year', function(){

  let selectedYear = $(this).val();
  
  setTimeout(function() {
    console.log(selectedYear);
  }, 2000);  // Try with 2 seconds to see the effect!
  
})

So the 3rd argument is a function statement... Stored for later execution. If that isn't clear, here is the reading you need.

Another thing... The second argument of setTimeout() is a required number. You used zero. That may be correct in some context, but not here. You should use a number for how many milliseconds of delay you want before the 1st argument (which, by the way, is a callback) executes.

Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64
  • No this doesn't solve my problem. I tried your way before posting here as well. It would have been so easy. Your codes give me same error. Thanks for trying. – Grogu Jan 18 '21 at 19:53
  • Right... I edited. I went to fast on this one. That is about `this` context... Another thing with a lot of reading to make... An common mistake in JS. I think I gave a lot of starters to you to learn more. – Louys Patrice Bessette Jan 18 '21 at 19:57