JS: The values printed by setTimeout are always taken from the previous iteration

This issue I'm facing is directly related to JS scope, and despite my efforts in research, I have not been able to find effective solutions from similar stackoverflow queries.

Here is the program in question:

http://jsfiddle.net/0z525bhf/

function write(x, y) {
    console.log(x);
    console.log(y);
}

var data = {
    "property": {
        "1": {
            "values": [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
        },
        "2": {
            "values": [[11, 12], [13, 14], [15, 16], [17, 18], [19, 20]]
        }
    }
}

var delay = 1000;

for (var x in data.property) {
    for (var i = 0; i < data.property[x].values.length; i++) {
        var one  = data.property[x].values[i][0];
        var two  = data.property[x].values[i][1];

        setTimeout(function() {
            write(one, two);
        }, delay);

        delay += 1000;
    }
}

This code snippet retrieves data from an object and iterates over both the object and its arrays. The goal is to display array values with a one-second gap between each, but it consistently shows only the values from the last iteration. Attempting to implement closures as suggested in other discussions has failed to resolve the issue.

Answer №1

When using the setTimeout function, it is not necessary to use a closure. You are able to directly pass variables to the timeout function like this:

for (var key in myData.entries) {
    for (var index = 0; index < myData.entries[key].items.length; index++) {
        var itemOne  = myData.entries[key].items[index][0];
        var itemTwo  = myData.entries[key].items[index][1];

        setTimeout(function(itemOne, itemTwo) {
            display(itemOne, itemTwo);
        }, delayTime, itemOne, itemTwo);

        delayTime += 1000;
    }
}

Answer №2

It would have been beneficial to conduct your own investigation and implement the following technique.

for (var i = 0; i < data.property[x].values.length; i++) {
    (function (one, two) {
        setTimeout(function() {
            write(one, two);
        }, delay);
    })(data.property[x].values[i][0], data.property[x].values[i][1]);

    delay += 1000;
}

Check out this functional jsfiddle: http://jsfiddle.net/0z525bhf/1/

Answer №3

One issue arises due to lexical closures: when you provide a function to setTimeout, it captures the variables one and two which are changed during each iteration. That's why it is advised to avoid defining a function within a for loop.

One way to resolve this problem is by using a functional loop:

var delay = 1000;
for (var x in data.property) {
  data.property.value[x].forEach(function (tuple) {
    var one = tuple[0], two = tuple[1];
    setTimeout(function() {
      write(one, two);
    }, delay);
    delay += 1000;
  });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilize Bootstrap modal to input information into the DataTables library

I am trying to use a bootstrap modal to insert data, but I am encountering an error on the action index. As a result, the button that I added is not functioning correctly. Can someone please review my code to see if there are any mistakes? User Action Con ...

The element is not positioned correctly due to the absolute positioning

This is my first attempt at creating a jQuery plugin and I have almost got it working correctly. You can view the example here. I've been struggling for days to position an element as desired. The goal is to display some text with an optional downwar ...

The TypeScriptLab.ts file is generating an error message at line 23, character 28, where it is expecting a comma

I am attempting to convert a ts file to a js file. My goal is to enter some numbers into a textarea, and then calculate the average of those numbers. However, I encountered an error: TypeScriptLab.ts(23,28): error TS1005: ',' expected. I have in ...

Send a parameter to be used as a link attribute in a pop-up box

I am seeking a way to pass a URL for my modal that relies on extracting the adder variable from the main HTML document. While I understand how to pass variables as text (using spans) to a modal, I am unsure how to incorporate a variable in an anchor <a ...

Explore various date formats using the datepicker functionality

I'm dealing with the code below: <script type="text/javascript" language="javascript" src="~/Scripts/bootstrap-datepicker.min.js"></script> <script type="text/javascript" language="javascript" src="~/Scripts/locales/bootst ...

The multiple-choice selection tool is not displaying any choices

I am having an issue with my ng-repeat code in conjunction with the jquery multiple-select plugin. Despite using this plugin for a multiple select functionality, the options generated by ng-repeat are not visible. Below is the code snippet in question: & ...

Create a JavaScript function that continues to execute even after a button has been clicked

Although it may seem like simple logic, I am currently unable to log in. Imagine I have a function called mytimer() stored in a common file that is linked to every HTML page. mytimer(){...........................}; Now, at some point on another page, whe ...

Is there a different term I can use instead of 'any' when specifying an object type in Typescript?

class ResistorColor { private colors: string[] public colorValues: {grey: number, white: number} = { grey: 8, white: 9 } } We can replace 'any' with a specific type to ensure proper typing in Typescript. How do we assign correct ...

Using unseralize in PHP allows you to transform the initial data into a different format

I have a string that needs to be unserialized in order to get the original values. $string3 = 'a:3:{i:0;a:2:{s:5:"value";d:4.0999999999999996;s:7:"players";a:2:{i:6;i:6;i:7;i:7;}}i:1;a:2:{s:5:"value";d:10.899999999999999;s:7:"players";a:1:{i:7;i:7;}} ...

Error message "Script start is missing" found in install.json for socket.io-php package

I am looking to develop a .io game that integrates with some PHP APIs, and I have been attempting to run the following files: install.json: { "name" : "workerman/phpsocket.io", "type" : "library", "keywords": ["socket.io"], "homepage": ...

Break down a string with various delimiters into an array with key-value pairs

Utilizing a module to facilitate the creation of booking orders on my website. This module offers a hook that triggers after a new booking is successfully created. The data I receive is stored in the variable booking_form, which contains the following in ...

Verify if function is returning sessionStorage using jest

Recently, I've been working on creating a jest test for the function below that sets a sessionStorage entry: /** * @desc create authenticated user session * @param {String} [email=''] * @param {Date} [expires=Date.now()] * @param {St ...

Saving the subtracted value from a span into a cookie until the checkbox is unchecked - here's how to

I am working on a piece of code that includes numeric values within a span. When the checkbox is clicked, it subtracts 1 from the main value, essentially reducing the total value. How can I achieve this so that even after the form is submitted, the deducte ...

Is it possible to enable password authentication on Firebase even if the user is currently using passwordless sign-on?

In my frontend JS project, I have integrated Firebase for web and am utilizing the passwordless (email link) authentication method for users. I am now interested in implementing password sign-on for an existing user who is currently using passwordless si ...

Google-play-scraper encounters an unhandled promise rejection

I'm trying to use the google-play-scraper library with Node.js, but I keep encountering an error when passing a variable as the 'appId'. How can I resolve this issue? Example that works: var gplay = require('google-play-scraper') ...

Extracting the name from a JSON key/value pair and then adding it to a TextField

Here is a sample JSON data: { "Id": 1, "Title": "Information on Jane Smith", "Comments": "Additional details here", "UpdatedBy": "Jane Smith", "UpdateDate": "May ...

After a push to the router, scrolling is disabled

While working on a Vuejs project, I encountered an issue when trying to change the page of my PWA using this.$router.push();. It seems to work fine everywhere else except when doing it from a modal within a component. The pushed page loads but scrolling is ...

Adding properties to Vue.js component in the script section without affecting rendering

How can I import component A with props and pass it to another component B for rendering? import MyComponent from '/MyComponent.vue' computed: { compnt: function () { var comp = MyComponent // How can I set props to MyC ...

Combining server-side and client-side routing in AngularJS: A comprehensive guide

Currently, I am in the process of transitioning a project to an Angular-based Single Page Application (SPA). The project is originally built using node/locomotivejs and serves templates from the server side. Due to its large size, we are converting it to A ...

Utilizing Formik and Material-UI Autocomplete for Handling Validation and Returning Object Values

When I submit my formik form, the values returned are in object format instead of just the selected value. The civility constant : const civility: { id: number; name: string; }[] = [ { id: 1, name: 'Mr' }, { id: 2, name: 'Ms' } ...