0

I need to search a large JSON file for an id and return all the attributes. However, there is a parentId attribute. This corresponds to the id of another object whose attributes I need to include, and possibly another parentId, etc.

m.getAttrs = function(o){
    var a = []

    // get the model based on id or object.id
    if(o instanceof String)
        var obj = json.models.filter(i => i.id == o)[0]
    else
        var obj = json.models.filter(i => i.id == o.id)[0]

    ////// On 2nd iteration: "TypeError: Cannot read property 'hasOwnProperty' of undefined" ///////////////
    if( obj.hasOwnProperty("parentId") && obj.parentId != ""){
        // get parent id
        var pid = obj.parentId

        // get parent attributes
        a.push(m.getAttrs(pid)) // RECURSION //
    }

    // get attributes
    var attrs = obj.attrids

    // get Attribute Names
    for(aid in attrs){
        var aName = json.attrs.filter(i => i.id == aid)
        a.push(aName)
    }

    return a
}

I'm seeing an error where obj is not defined after the first iteration of getAttrs. I think this is because json.models.filter... isn't finished, but it could be a lot of things.

I've tried a bunch of times to implement promises, but can't seem to get anything working, and it makes my code too messy for me to want to include it here.

How can I implement a promise to say "after you find the right model, CONTINUE (rather than execute another function)"?

Travis Heeter
  • 13,002
  • 13
  • 87
  • 129
  • 2
    What is `json.models`? If it's just an array, that's finished before the next line of code is run (`Array.prototype.filter` is synchronous). – T.J. Crowder Mar 09 '17 at 16:53
  • `json.models` it is an array of objects. Good to know `.filter` is synchronous - thanks. So you're saying the problem isn't with async, it's with filter perhaps? – Travis Heeter Mar 09 '17 at 16:57
  • If `json.models` is an array, you definitely won't get `TypeError: Cannot read property 'hasOwnProperty' of undefined` from the line you've indicated above. `obj` will be an array (for sure), which has `hasOwnProperty`. – T.J. Crowder Mar 09 '17 at 17:00
  • Note that since `obj` will be an array, unless you've been doing things to `Array.prototype`, `obj` will not have a `parentId` value. Did you mean `json.models.find` rather than `json.models.filter`? – T.J. Crowder Mar 09 '17 at 17:01
  • 1
    It doesn't seem like the code causing the problem is in the question. Please update your question with a **runnable** [mcve] using Stack Snippets (the `[<>]` toolbar button), demonstrating the problem. – T.J. Crowder Mar 09 '17 at 17:02
  • `obj` is an object. `json.models` is an array of objects. Sorry forgot [0]. – Travis Heeter Mar 09 '17 at 17:07
  • Why *retype* rather than copy and paste?! What other code above isn't quite like your real code? Anyway, the error tells you that the ID wasn't found. (`filter()[0]` is an anti-pattern. Use `find()`, polyfilling if necessary.) – T.J. Crowder Mar 09 '17 at 17:16
  • If that was the case, why would it work for the first iteration, and not the subsequent iterations? – Travis Heeter Mar 09 '17 at 17:28
  • There's no "if" about it. Why is `obj` undefined? Probably, `o` is different, and not found. The code above doesn't iterate, so we can't help you debug iterations. – T.J. Crowder Mar 09 '17 at 17:30
  • Why do you say it doesn't iterate? It for sure iterates (recursively). I added a comment to show where that happens. Sorry, I changed the name to make it easier to understand and forgot to change the recursive call. – Travis Heeter Mar 09 '17 at 17:32
  • Once again you've changed the code. The code [that was there](http://stackoverflow.com/revisions/42701004/2) when I posted that comment called a function called `getAllAttributes` from a function called `getAttrs`. No recursion there. **Now** it recurses (which isn't iteration, but never mind). So: Clearly `pid` doesn't identify an entry in `json.models`. You'll have to debug to know why that is. – T.J. Crowder Mar 09 '17 at 17:38
  • 1
    All due respect, I recommend deleting this question, working through the code with the debugger built into your browser, and if you can't work it out, post a new question with your **actual** code, ideally in the form of an [mcve], so you're not wasting your own time and other people's with code that isn't what you're actually using. – T.J. Crowder Mar 09 '17 at 17:39
  • ...or presumably this code could be turned into a MCVE by just showing the example javascript object being used (`json`),the value passed to the initial call (`o`) to `getAttrs` and the expected output – Jamiec Mar 09 '17 at 17:40
  • I think the question is still valid: "How to use promises to continue operation?" You're the one trying to debug my code. – Travis Heeter Mar 09 '17 at 17:40
  • 1
    @TravisHeeter the answer to that is "you shouldnt" - at least not sensibly. promises are primarily for async code, your code is entirely sync – Jamiec Mar 09 '17 at 17:40
  • OK, the problem is `instanceof`. @Jamiec, I will delete the question if you think that's best, but I think it would be more helpful to others if you posted your last comment as an answer - including the bit about `filter` being synchronous. – Travis Heeter Mar 09 '17 at 17:47
  • Im sorry, i dont follow the bit about `instanceof`. Dont delete your question, fix it. You dont want a promise you want to know how to fix your logic - that we can do with a [mcve] – Jamiec Mar 09 '17 at 17:49
  • See [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – georgeawg Mar 09 '17 at 18:32

1 Answers1

0

Here's what I found out...

  • According to Jamiec, It is not possible to use a promise to continue regular operation. Although it seems like a generator may be able to accomplish this, but I'm not familiar with them.
  • Array.prototype.filter is synchronous, so my issue wasn't with async in the first place. It turns out that instanceof String doesn't work unless you specifically make a String variable. Here's a post I found to help with that: Why does instanceof return false for some literals?

This fixed my code:

if(typeof o === "string")
    var obj = json.models.filter(i => i.id == o)[0]
else
    var obj = json.models.filter(i => i.id == o.id)[0]
Travis Heeter
  • 13,002
  • 13
  • 87
  • 129