DEV Community

Discussion on: What are you struggling with? (frontend)

 
andi23rosca profile image
Andi Rosca

I'm still not quite sure where the problem lies. Is it the recursivity? Maybe if you can share the exact piece of code where stuff strats to break down?

Thread Thread
 
octaneinteractive profile image
Wayne Smallman

First, assetGraph() is called, via the API:

'use strict'

let services = {}

// Notes.

const Notes = require('../models/notes')

let graph = {
  nodes: [],
  edges: []
}

// Methods.

services.assetGraph = async (params) => {

  if (graph.nodes.length > 0)
    graph.nodes = []

  if (graph.edges.length > 0)
    graph.edges = []

  const acyclicalGraph = await services.acyclicalBuildingOfGraph(params.userID, params.noteID)

  console.log("Perspective:assetGraph()", graph)

  return acyclicalGraph

}

services.acyclicalBuildingOfGraph = (userID, noteID, visited = [], depth = 0, maxDepth = 5) => {

  console.log("Perspective:acyclicalBuildingOfGraph()", userID, noteID, visited, depth, maxDepth)

  return new Promise((resolve, reject) => {

    userID = parseInt(userID)
    noteID = parseInt(noteID)

    if ( depth > maxDepth )
      return

    if ( visited.includes(noteID) )
      return
    else
      visited.push(noteID)

    services.getAsset({
      id: noteID
    }).then(asset => {

      let assetInQuestion = asset[0].dataValues

      services.getLinksToAsset({
        user_id: userID,
        note_id: noteID
      }).then(linksTo => {

        graph.nodes.push({
          data: {
            id: parseInt(noteID),
            creation: assetInQuestion.creation,
            modification: assetInQuestion.modification,
            title: assetInQuestion.title,
            depth: depth,
            weight: (maxDepth - depth)
          }
        })

        // console.log("Perspective:acyclicalBuildingOfGraph():node", graph.nodes.length)

        if ( linksTo.length > 0 ) {

          let assetsLinkedTo = linksTo[0].dataValues.NotesLinksFrom

          let i = assetsLinkedTo.length

          assetsLinkedTo.forEach(async link => {

            // console.log("Perspective:acyclicalBuildingOfGraph():iteration", i)

            let linkedNoteId = link.to_asset

            let edgeID = `${noteID}->${linkedNoteId}`

            if ( services.findDuplicateEdgeId('id', edgeID) === false ) {

              graph.edges.push({
                data: {
                  id: edgeID,
                  weight: (maxDepth - depth),
                  source: parseInt(noteID),
                  target: parseInt(linkedNoteId)
                }
              })

            }

            await services.acyclicalBuildingOfGraph(userID, linkedNoteId, visited, depth + 1)

          })

          // console.log(`Perspective:acyclicalBuildingOfGraph():graph:${depth}:`, graph.edges)

          return resolve(graph)

        }

      })

    })

  })

}

services.getAsset = (params) => {
  return Notes.getAsset(params)
}

services.getLinksToAsset = (params) => {
  return Notes.getLinksToAsset(params)
}

services.findDuplicateEdgeId = (field, value) => {

  // console.log("Perspective:findDuplicateEdgeId()", edges)

  if ( graph.edges.length > 0 ) {
    for (const [index, edge] of Object.entries(graph.edges)) {

      // console.log("Perspective:findDuplicateEdgeId():for", index, edge)

      if (edge[field] === value) {
        return index
      }
    }
  }

  return false

}

module.exports = services
Thread Thread
 
andi23rosca profile image
Andi Rosca • Edited

I think stuff starts to break down because you return inside the Promise in services.acyclicalBuildingOfGraph. If you don't call resolve or reject in a Promise it will never actually finish.

The problems I see are mostly around the confusion with async code in javascript. I'm assuming you need to use async code because Notes.getLinksToAsset(params) or similar calls are fetching stuff?

Async/await syntax is just syntactical sugar over promises, meaning that when you create an async function, it actually creates a function that returns a promise "under the hood". And when you say return inside of an async function it's like calling the resolve function of the Promise. But it doesn't automatically resolve normal promises.

I'd say you should put empty resolve() statements right before your returns, so that the Promise will actually finish. You can also just do resolve(graph) instead of return resolve(graph).
And at least your code should execute. You can take it from there and see if it actually does what it's supposed to do.

Thread Thread
 
octaneinteractive profile image
Wayne Smallman

I've narrowed it down to something in Vue rather than Node

Andi, thanks for the time, much appreciated.