FileAttachment in ObservableHQ - different behaviour if within 2 cells or 1: TypeError: reading.map is not a function

Viewed 654

If I put the following code within a single Observable HQ cell, I get

data5 = TypeError: reading.map is not a function

data5 = {
  const reading = FileAttachment("climate_graphs - china.csv").csv();
  reading.map(function(element) {
    return {"date": element["date"], "value": element["value"]}
  })
}

However, if I break it up into 2 cells, it works:

// cell 1
reading = FileAttachment("climate_graphs - china.csv").csv();


// cell 2
data = reading.map(function(element) {
  return {"date": element["date"], "value": element["value"]}
})
1 Answers

In the documentation for FileAttachment it calls out that .csv() is an async method of FileAttachment:

Calling FileAttachment doesn’t immediately load the file—the contents are only loaded when you request them. It’s a bit like the Fetch API: there are async methods that return the file’s contents in different forms, such as JSON, CSV, or ArrayBuffer. You choose the appropriate method based on how you want to consume the file.

But it could be clearer for this issue in that in the latter case the where you have 1 cell to read the file/ 1 cell to process the data; that the file is read and assigned to reading with implicit async/ await. And, that in the case where you have the error that you need to specify await in the block.

So, this should work:

data5 = {
  // use await below
  const reading = await FileAttachment("climate_graphs - china.csv").csv();
  // 'reading' is now an array of objects so can use 'map'
  let mapping = reading.map(function(element) {
    return {"date": element["date"], "value": element["value"]}
  });
  return mapping;
}

Generally, that cells have this Promise-specific behaviour is referred to in the documentation in Introduction to Promises:

Did you see the promise? Observable implicitly awaits promises across cell boundaries, so you often don’t need to deal with a promise directly. Cells can return promises, and other cells can simply refer to the values and they’ll run when the promise resolves.

Related