Hi Aaron, the methods you sketched above are not equivalent, and it’s important to understand why.
First, d3.csv()
returns a Promise, not an array. So the way JS evaluates this:
var url_source = d3.csv('https://...')
var input = document.getElementById('exampleInputEmail3')
input.value = url_source[0].url_orig;
is roughly as follows.
-
url_source
is created as a Promise. It will resolve when the request to the URL succeeds (or fails), however, that will take a fairly long time compared to the evaluation of other code, so JS doesn’t wait for it and moves to the next lines: -
input
is set to the html element with IdexampleInputEmail3
, and then -
input.value
is set tourl_source[0].url_orig
. At this point,url_source
is still an unresolved Promise, so url_source[0] is undefined. Then.url_orig
doesn’t exist, so you get the error that you quoted above. -
At some point, url_source resolves, but the above steps have already been performed, so this has no effect.
One thing you can do to get that cell to work in Observable is to throw an await
in front:
var url_source = await d3.csv('https://...')
var input = document.getElementById('exampleInputEmail3')
input.value = url_source[0].url_orig;
That causes the evaluation of the JS to pause until url_source
has resolved. I believe this is what happens implicitly in Observable when you separate the request into different cells:
var url = external_data
var input = document.getElementById('exampleInputEmail2')
input.value = url[0].url_orig;
external_data = d3.csv('https:...')
Observable waits for external_data to resolve before evaluating the first cell. Note that separating code into different Observable cells is not equivalent to putting code in different script tags!
In any case, this is not a good solution for a page on the web since what this does is to lock the other code as well as the rendering of the page until the request finishes, which will lead to poor performance and a bad user experience.
A much better approach is to make use of the Promise API as you did in your followup post. The then
syntax performs the given function automatically when the request resolves without blocking the rest of the code on the page.
Promises are a bit confusing but very important to the way we get data from other sources on the web, so I recommend spending some time with the docs or looking at some other tutorials (there are many out there!).