# Type error .join() not a function

**URL:** <https://talk.observablehq.com/t/type-error-join-not-a-function/2060>\
**Category:** Help\
**Created:** [June 15, 2019, 1:40pm UTC](https://talk.observablehq.com/t/type-error-join-not-a-function/2060 "2019-06-15T13:40:27Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![maliky](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/maliky/32/706_2.png) [@maliky](https://talk.observablehq.com/u/maliky)\
**Post date:** [June 15, 2019, 1:40pm UTC](https://talk.observablehq.com/t/type-error-join-not-a-function/2060/1 "2019-06-15T13:40:27Z")

</div>

Hi,

I really have a hard time grasping (several month, if no a year of confused learning) how to handle external dataset in js or d3. I kind of feel like a monkey in a library. It may have been my js skills so I checked what I knew on [sololearn.com](http://sololearn.com). Completed the tutorial in javascript, finding it easy. So there must be something else, a twist of mind I can’t take and I don’t know why.

The last three days I’ve bee trying to learn how to use the force and simulation functions for networks. I have two approaches:

1. port some code locally
2. fork some notebook and change the dataset.

I’m failing on both.

1. Starting with [https://observablehq.com/@d3/disjoint-force-directed-graph](https://observablehq.com/@d3/disjoint-force-directed-graph) I downloaded the graph.json and reproduced the following js code in a file.

```auto
    const height=600,
          width = 600;

    d3.json('./data/graph.json')
        .then(function(data) {
    	const links = data.links.map(d => Object.create(d));
    	const nodes = data.nodes.map(d => Object.create(d));

    	const simulation = d3.forceSimulation(nodes)
    	      .force("link", d3.forceLink(links).id(d => d.id))
    	      .force("charge", d3.forceManyBody())
    	      .force("x", d3.forceX())
    	      .force("y", d3.forceY());

    	// create the DOM element for the view Box
    	const svg = d3.select("#canvas")
    	      .attr("viewBox", [-width / 2, -height / 2, width, height]);

    	const link = svg.append("g")
    	      .attr("stroke", "#999")
    	      .attr("stroke-opacity", 0.6)
    	      .selectAll("line")
    	      .data(links)
    	/*
    	  mbnetwork.js:26 Uncaught (in promise) TypeError: svg.append(...).attr(...).attr(...).selectAll(...).data(...).join is not a function
    	  at mbnetwork.js:26
    	  (anonymous)	@	mbnetwork.js:26
    	  Promise.then (async)		
    	  (anonymous)	@	mbnetwork.js:5
    	*/
    	      .join("line")
    	      .attr("stroke-width", d => Math.sqrt(d.value));

    	const node = svg.append("g")
    	      .attr("stroke", "#fff")
    	      .attr("stroke-width", 1.5)
    	      .selectAll("circle")
    	      .data(nodes)
    	      .join("circle")
    	      .attr("r", 5)
    	      .call(drag(simulation));

    	node.append("title")
    	    .text(d => d.id);

    	// what is the on tick?
    	simulation.on("tick", () => {
    	    link
    		.attr("x1", d => d.source.x)
    		.attr("y1", d => d.source.y)
    		.attr("x2", d => d.target.x)
    		.attr("y2", d => d.target.y);

    	    node
    		.attr("cx", d => d.x)
    		.attr("cy", d => d.y);
    	});

    	invalidation.then(() => simulation.stop());

        })

    function drag(simulation) {
        // Qu'est ce que d3.event.active ?
        function dragstrated(d){
    	// si il y a pas d'évenement actif restart simulation ?
    	// d3.event.active the number of currently active drag gestures, drag gesture ?
    	// 0 on start and end
    	if (!d3.event.active) simulation.alphaTarget(.3).restart();
    	// the above is true on start and end drag gestures
    	// set de the element speed ?
    	d.fx = d.x;
    	d.fy = d.y;
        }

        function dragended(d) {
    	// how is the diff made between start and end ?
    	if (!d3.event.active) simulation.alphaTarget(0);
    	d.fx = null;
    	d.fy = null;
        }

        function dragged(d) {
    	d.fx = d3.event.x;
    	d.fy = d3.event.y;
        }

        return d3.drag()
    	.on("start", dragstarted)
    	.on("drag", dragged)
    	.on("end", dragended);
    }

```

But as indicated in the code, I get an Type error .join() is not a function. I don’t understand it.

1. Also I get a similar message `chart = TypeError: svg.node is not a function` when trying use my own xml dataset. [https://observablehq.com/@maliky/afficher-un-reseau-dans-la-vue](https://observablehq.com/@maliky/afficher-un-reseau-dans-la-vue)

I guess there are related by I have no clue how to solve them.

Thank you

---

<div class="post-metadata">

**Author:** ![j-f1](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/j-f1/32/368_2.png) [@j-f1](https://talk.observablehq.com/u/j-f1)\
**Post date:** [June 15, 2019, 2:53pm UTC](https://talk.observablehq.com/t/type-error-join-not-a-function/2060/2 "2019-06-15T14:53:28Z")

</div>

I think I’ve solved the issue for you with [this suggestion](https://observablehq.com/compare/84b129f376f19eb4@229...658b21ea84f7e03c@232). The problem was that your code declared the `svg` variable in the callback of the `then` method. This meant that when you returned `svg.node()`, you were referring to the `svg` variable that the Observable standard library provides. My suggestion updates your code to use `await` to eliminate the callback.

---

<div class="post-metadata">

**Author:** ![maliky](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/maliky/32/706_2.png) [@maliky](https://talk.observablehq.com/u/maliky)\
**Post date:** [June 15, 2019, 3:03pm UTC](https://talk.observablehq.com/t/type-error-join-not-a-function/2060/3 "2019-06-15T15:03:10Z")

</div>

Ok, Thank you. Yes it was scope version and your suggestion help. Although, I’m not quite sure about the usage of await in that context. My understanding is that we should use await, and moving the svg declaration in the above scope was enough to solve that problem.
