简体   繁体   中英

Efficient way to handle JS function ordering

I'm fairly new to JS and am still slightly confused, by the ordering and nesting of JS functions. I have a script that I want to occur in a specific way. The problem a criteria can be left blank by a user. Im trying to say if the variable length is greater than zero run the callback, but then move into the code that occurs under the next two if statements. I know there must be a more efficient method for this, but for the life of me I can't think of one besides placing all the other code under each different if/else statement.

var lst = []
var lst2 = []
var lst3 = []

alert(cityu);
alert(dateu);
alert(numberu);

d3.csv("kyle.csv", function (d) {
    return {
        city: d.from,
        number: d.phone_number,
        date: d.from_date
    };
}, function (error, rows) {
    if (dateu.length > 0) {
        for (var i = 0; i < rows.length; i++) {
            if (rows[i].date === dateu) {
                lst.push(rows[i]);
                console.log(rows[i]);
            }
        }
    } else {
        if (cityu.length > 0) {
            for (var i = 0; i < lst.city.length; i++) {
                if (lst.city[i] === cityu) {
                    lst2.push(lst[i]);
                    console.log(lst2);
                }
            }
        } else {
            if (numberu.length > 0) {
                for (var i = 0; i < rows.length; i++) {
                    if (lst.number[i] === numberu) {
                        lst3.push(lst2[i]);
                        console.log(lst3);
                    }
                }
            }
        }
    }
})
};

Here you can see that if the dateu variable has length greater than zero the rows in a csv matching that user entered criteria will be pushed to the array "lst". Obviously it currently doesn't move into the next callback under, it will only do this if "dateu" equalled zero.

One other issue with my script is that at each if statement I hope to reduce my original input based on the user entered parameters. For example a user might enter "seattle" the variable "city" will now equal seattle and only rows containing Seattle as their city will be kept in the array that rows[i] is pushed to.

Every piece of user input shown here:

alert(cityu);
alert(dateu);
alert(numberu);

will have the same affect on the dataset, each time reducing the number of rows included.

The problem specifically is that each if statement relies on the array from the previous callback.

Your code redone a little - I've removed the else blocks, because you want to do each loop regardless of the previous loop

if(condition1) {
    do something
}
else {
    do something else
}

from that, if the first condition is met, the else block wont get executed

if(condition1) {
    do something
}
if(condition2) {
    do something else
}

In this case, do something else only relies on condition2 being true, consition1 is irrelevant

    var lst = []
    var lst2 = []
    var lst3 = []

    alert(cityu);
    alert(dateu);
    alert(numberu);

    d3.csv("kyle.csv", function(d) {
        return {
            city: d.from,
            number: d.phone_number,
            date: d.from_date
        };
    }, function(error, rows) {
        var i;
        if (dateu.length > 0) {
            for (i = 0; i < rows.length; i++) {
                if (rows[i].date === dateu) {
                    lst.push(rows[i]);
                    console.log(rows[i]);
                }
            }
        }
        if (cityu.length > 0) {
            for (i = 0; i < lst.city.length; i++) {
                if (lst.city[i] === cityu) {
                    lst2.push(lst[i]);
                    console.log(lst2);
                }
            }
        }
        if (numberu.length > 0) {
            for (i = 0; i < rows.length; i++) {
                if (lst.number[i] === numberu) {
                    lst3.push(lst2[i]);
                    console.log(lst3);
                }
            }
        }
    });
};

One minor inconsequential change, moved the declaration of var i to the top of the function block, because technically you were declaring it three times, and jslint/jshint would complain - though nothing would break (yet)

I'm still not completely sure on your logic, but looking at Tiny Giant's gist, it seems like there are only three combinations:

1) Only dateu exists.

2) dateu and cityu exist.

3) dateu , cityu , and numberu exist.

So you don't care about the condition where dateu and numberu exist, but cityu is empty, right?

Okay , I reread your code. It seems like you have rows, and you have three possible filters. Filter rows based on AND , for example cityu AND dateu .

If so, here's a giant refactor. Just as a note, there may be some JavaScript errors because I had no way of testing this. But the code is fairly simple and straightforward:

for (key in activeFilters) {
  if (rows[i][key] === activeFilters[key]) {
    addRow = true;
    break;  // if one is true, that's good enough for an OR
  } else {
    addRow = addRow || false;
  }
}

if (addRow) {
  filteredList.push(row[i]);
  // reset addRow for the next row
  addRow = false;
}

If you're filtering using OR , then you'll need to change your comparison to something like this:

 for (key in activeFilters) { if (rows[i][key] === activeFilters[key]) { addRow = true; break; // if one is true, that's good enough for an OR } else { addRow = addRow || false; } } if (addRow) { filteredList.push(row[i]); // reset addRow for the next row addRow = false; } 

Hope this was closer to your intended logic!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM