0

new to JS and I'm trying to wrap my head around Promises that I could use some insight.

let urlPath = "some urlpath with data"
let data = d3.csv(urlPath).then(function (d) { 
       console.log(d);                     // Prints data as expected
});

My goal is that I want the function to return the data into the DATA variable so that I can continue to execute on it further down in the code. So something similar to below:

let data = d3.csv(urlPath).then(function (d) { return d; });
//....do more things with data....
console.log(data); // returns Promise { pending }

But the code keeps giving me Promise {pending}. Any ideas how I can resolve the promise so that I get what I'm looking for? Thanks,

Charlie P
  • 51
  • 2
  • 8
  • You cannot do this the way you are trying. Please show a [MCVE] to illustrate more fully what you are trying to do. – Code-Apprentice Oct 05 '18 at 15:45
  • In Javascript, you can never return asynchronous data directly from a function. The function itself returns BEFORE the asynchronous callback is even called and before the data is available. Thus, you have to either return a promise that the caller will use `.then()` on or accept a callback that you can call when you have the data and the caller uses that callback. See [How do I return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call/14220323#14220323) for a more detailed discussion. – jfriend00 Oct 08 '18 at 21:32

1 Answers1

2

This is not possible with ECMAScript 2015 edition. However, with ES2017, you can achieve this in an async IIFE using await:

(async () => {
  let data = await d3.csv(urlPath)
  //....do more things with data....
  console.log(data)
})()

For error handling, you can wrap it in a try...catch:

(async () => {
  try {
    let data = await d3.csv(urlPath)
    //....do more things with data....
    console.log(data)
  } catch (error) {
    // handle error
  }
})()

This is analogous to the following in ES2015:

d3.csv(urlPath).then(data => {
  //....do more things with data....
  console.log(data)
}).catch(error => {
  // handle error
})
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • The OP says: "My goal is that I want the function to return the data" which is simply not possible. As I'm sure you know, `async/await` only works inside the function itself. There is no way in any version of Javascript to directly return asynchronously retrieved data. One must return the promise and the caller then uses `.then()` or `await` on that returned promise. – jfriend00 Oct 08 '18 at 21:33
  • @jfriend00 sure, but the focus of the goal was to get data into the `data` variable. That has been achieved. As _you_ know, the OP asked a question in XY problem-form, and I gave an answer which side-stepped the approach they were initially trying to take. Does that make the answer invalid? – Patrick Roberts Oct 08 '18 at 21:37
  • Thanks for all the advice. In short this is how I went about it: `d3.csv(urlPath).then(function (d) { let scale = d3.scaleLinear() .domain(d3.extent(d)) .range([0, 500]); canvas.selectAll("rect") .data(d) .enter() .append("rect") .attr("fill", "blue") .attr("width", function (y) { return scale(y); }) .attr("height", 500 / d.length-1) .attr("y", function (y, i) { return i * (500 / d.length); }) });` – Charlie P Oct 10 '18 at 21:36