async function countRowsHandler() {
  const url = ui.getQueryElement().value;
  ui.updateStatus(`Building data object to connect to ${url}`);
  const myData = tf.data.csv(url);
  let i = 0;
  ui.updateRowCountOutput(`counting...`);
  const updateFn = x => {
    i += 1;
    if (i % 1000 === 0) {
      ui.updateStatus(`Counting ... ${i} rows of data in the CSV so far...`);
    }
  };
  try {
    ui.updateStatus('Attempting to count records in CSV.');
    // Note that `tf.data.Dataset.forEachAsync()` is an async function.  Without
    // the `await` here, there is no control over when the updataFn's will
    // execute, thus, they will likely execute *after* we update the status with
    // the final count, resulting in a display of "Counted 0 rows.".
    await myData.forEachAsync(x => updateFn(x));
  } catch (e) {
    const errorMsg = `Caught an error iterating over ${url}.  ` +
        `This URL might not be valid or might not support CORS requests.` +
        `  Check the developer console for CORS errors.` + e;
    ui.updateRowCountOutput(errorMsg);
    return;
  }
  ui.updateStatus(`Done counting rows.`);
  ui.updateRowCountOutput(`Counted ${i} rows of data in the CSV.`);
}
Builds a CSV Dataset object using the URL specified in the UI.  Then iterates
over all elements in that dataset to count them.  Updates the UI accordingly.