3

Please refer to the image attached.

This is my first node app/script and I am trying to understand why I am getting different results when I attach .then(console.log): at the end vs. when I just use console.log(list);.

https://i.stack.imgur.com/FnOLv.jpg

In case the image doesn't load here is the snippet

// Generate list
const list = r.getSubreddit('AskReddit')
    .getTop({ time: 'all', limit: 1 })
    .map(post => ({
        title: post.title,
        url: post.url,
        upvotes: post.ups
    }))
    .then(console.log);

// console.log(list);

I get this error message:

internal/util/inspect.js:373
  const symbols = Object.getOwnPropertySymbols(value);
                         ^

TypeError: 'ownKeys' on proxy: trap result did not include 'prototype'
    at Function.getOwnPropertySymbols (<anonymous>)
    at getKeys (internal/util/inspect.js:373:26)
    at formatRaw (internal/util/inspect.js:617:12)
    at formatValue (internal/util/inspect.js:540:10)
    at inspect (internal/util/inspect.js:197:10)
    at Object.formatWithOptions (util.js:84:12)
    at Console.(anonymous function) (internal/console/constructor.js:274:15)
    at Console.log (internal/console/constructor.js:284:61)
    at Object.<anonymous> (/Users/ik/Documents/Personal/list.js:27:9)
    at Module._compile (internal/modules/cjs/loader.js:799:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
    at Module.load (internal/modules/cjs/loader.js:666:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
    at Function.Module._load (internal/modules/cjs/loader.js:598:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:862:12)
    at internal/main/run_main_module.js:21:11
ik3o
  • 39
  • 5
  • `list` isn't an array, it's a promise. As for the error, I guess it has something to do with how bluebird promises are implemented, which make them troublesome to naively log in a console. – Patrick Roberts Aug 08 '19 at 04:08
  • Actually, `snoowrap` itself uses a `Proxy` for the method chaining syntax, and their implementation does not support general inspection of the object. Just follow their documentation to use the API appropriately. – Patrick Roberts Aug 08 '19 at 04:23

2 Answers2

0

The first call ‘r.getSubreddit(...).getTop(...).map(..)’ is returning a promise. That’s why you can the call ‘.then(console.log)’

The ‘.then’ says “do this once the promise is fulfilled, or, in other words, when the call from getSubreddit is completed.

When you say ‘console.log(list)’ you are asking for a value that may or may not exist. You create the promise and JavaScript immediately invokes the next call, which is your console.log, and lists is still waiting for the promise to resolve. When you use a .then() you are saying “wait for this promise to resolve before console.logging the output.”

westandy
  • 1,360
  • 2
  • 16
  • 41
  • When you write `console.log(list)` you're actually logging an object (i.e. the `Promise`) that encapsulates the value which may or may not exist. But at that point it definitely does not exist. None of this explains why the error is thrown though. – Patrick Roberts Aug 08 '19 at 04:16
  • 1
    Thank You for the easy explanation! I get the difference between the two now. – ik3o Aug 08 '19 at 16:29
  • Don't forget to plus one the answers and/or check one that you feel is the correct answer so the authors get credit. I'm glad you're getting the asynchronous nature of JavaScript. Wait till you get to async/await which are even easier than Promises. – westandy Aug 08 '19 at 22:45
0

It seems you are using snoowrap, and according to the source code (see snoowrap.js), getTop() returns a Promise, which means you must attach your then statement to that. If getTop() returned an array, you could latch on the map statement as you did, but it doesn't, it returns a Promise.

Try this:

const list = r.getSubreddit('AskReddit')
    .getTop({ time: 'all', limit: 1 })
    .then(console.log);

Or with the map:

const list = r.getSubreddit('AskReddit')
    .getTop({ time: 'all', limit: 1 })
    .then((topPosts) => {
        return topPosts.map(post => ({
            title: post.title,
            url: post.url,
            upvotes: post.ups
        })
    })
    .then(console.log);

Either way, as a side note, please do note what previous commenters said about your second console.log. Since you're using Promises, the action of getting the Subreddit is asynchronous, which is why you have to chain all the commands together, doing each step when the previous is complete. So to log the actual result, it would have to be in the then statement.

I'd recommend doing some homework on Promises:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises


EDIT:

Since snoowrap is using Bluebird under the hood for Promises, I might be wrong, and actually you can use map the way you did, since Bluebird includes this. Interestingly, the Promises this library is using is a wrapper over the usual Promise object. Maybe they're implementing that wrapper incorrectly, using it as a proxy that isn't designed correctly, similar to the problem in this question:

TypeError: 'ownKeys' on proxy: trap result did not include 'arguments'

Partik
  • 808
  • 9
  • 15