DEV Community

Discussion on: Like `console.log` But Better

Collapse
 
davidmaxwaterman profile image
Max Waterman

in some cases console.log does not print the true value of its arguments

What's the story there? Any more detail?

Thread Thread
 
bernardbaker profile image
Bernard Baker

It's related to JSON.stringify().
I was programming and the console.log as a source of truth didn't match the expected output.

So I researched my problem and found a snippet. Which mentioned JSON.stringify() in a console.log() call.

Which displays the actual value of an argument passed to it.

Thread Thread
 
davidmaxwaterman profile image
Max Waterman • Edited

Is it to do with this (?):

stackoverflow.com/questions/738906...

If you follow the reference to the example in jsfiddle, you can see the problem:

jsfiddle.net/luken/M6295/

It looks like console.log does a synchronous evaluation of the object when the console is open, but if the console is closed when the call is made, and opened after the call, then it is asynchronous and you get the 'unexpected' values.

I guess I've never seen this because I always have the console open.

Also:

developer.mozilla.org/en-US/docs/W...

"Logging objects
Don't use console.log(obj), use console.log(JSON.parse(JSON.stringify(obj))).

This way you are sure you are seeing the value of obj at the moment you log it. Otherwise, many browsers provide a live view that constantly updates as values change. This may not be what you want."

Thread Thread
 
bernardbaker profile image
Bernard Baker

The developer docs from MDN explain it well.

I don't think having the console open made a difference in my case.

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

Yeah, but seeing it in action helps too - it also helps you see it in your 'dev tools of choice', in case you think it doesn't happen for you.

It's interesting it didn't make any difference for you, but perhaps it was a more normal case of delayed evaluation, like you can get with using objects in a closure (I think the classic example is loop variables used in an event handler that was added inside the loop)?

Thread Thread
 
bernardbaker profile image
Bernard Baker

I recall my scenario was objects and key value assignment.

Seeing it in action would help too.

As I remember it was open and by passing a reference I was presented with different stale key pair values.

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

Hrm. That's curious. It sounds almost the opposite of how I understand the problem - ie that it would display newer values than you would expect because the evaluation of the object happens later than expected.

If I understand the scenario you describe, it would be something like this:

var myVar = {a: true};
var myVar2 = {};

...

myVar2.b = myVar; // {b: {a: true})

myVar.a = false;

...

console.log(myVar2); //?? got { b: { a: true } } but expected { b: { a: false } )

Or something like that? Perhaps you could try an example to help us see what you mean.

Thread Thread
 
bernardbaker profile image
Bernard Baker • Edited
var myVar = {a: true};
var myVar2 = {};
myVar2.b = myVar; // {b: {a: true})
myVar.a = false;
console.log(myVar2); // === {b: {a:false}}
Thread Thread
 
davidmaxwaterman profile image
Max Waterman

Hrm, yeah. I can't see how that can happen.

Thread Thread
 
bernardbaker profile image
Bernard Baker

I think the main point is that if a developer is working with any data structure and the output scheduled by the .log doesn't seem to be correct then they can employ the use of JSON.parse /.stringify to obtain a source of truth.

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

Yeah, perhaps. Just being aware that it might not output what you expect is an eye-opener for me - so thanks for making us aware :D

Thread Thread
 
bernardbaker profile image
Bernard Baker

Have you used generators?

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

No, I haven't. I looked into them at one point, but found them too 'mind bending'. As I understand it, async/await uses them, so perhaps I have without knowing I was....or perhaps they're not related at all and I've completely mis-remembered.
Why do you ask?

Thread Thread
 
bernardbaker profile image
Bernard Baker

Our conversation seemed like it was going to end. So I proposed a new topic.

I checked online and you may have misunderstood. Generators execute sequentially using yield.

Async/await makes it easy to implement a use case of generators.

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

Hrm, I don't think I misunderstood. generators came a year before async/await and the latter was a classic follow-on from generators. Of course, I could be mis-remembering, or not putting it correctly...here I found a reference:

"

  1. Async/await makes it easier to implement a particular use case of Generators.
  2. Async function can be decomposed into Generator and promise implementation which are good to know stuff. "

overflowjs.com/posts/Javascript-Ge...

TBH, I never quite got my head around it. Apparently, it is something that came from the Python world, and some of my 'back end' colleagues rave about it. I've never found a need, but perhaps I would if I 'internalised' them better - perhaps I should take a class or something.

Thread Thread
 
bernardbaker profile image
Bernard Baker

I've used generators and they help when you sequentially need to execute a series of asynchronous calls using await. Which is better than using promises which execute promises.then().

So you can yield the value of the await if I remember correctly. And then perform error handling before moving on to the next operation which is part of the series of asynchronous calls.

Thread Thread
 
davidmaxwaterman profile image
Max Waterman • Edited

That's odd/interesting. Is that different than the basic use-case of 'await'? ie

await doThis();
await thenDoThis();
await andFinallyDoThis();

?

Is the difference in the error handling, which you would likely do with a try-catch? Got a snippet to illustrate what you mean?

Thread Thread
 
bernardbaker profile image
Bernard Baker

I used generators with npm redux-sagas/effects

import { call, put } from "redux-sagas/effects";
import Service from "./Sevice";
export const foo* = (action) => {
  const data = yield call(Service.getData, action.userId)
  // do something with the data...
}
Thread Thread
 
davidmaxwaterman profile image
Max Waterman

Hrm, ok. That doesn't parse to my eyes. I have some code written by a contractor we used that is just as difficult for me to grok now that he's left. I find Redux to be very obtuse. I like the concept on a high level, but the implementation makes my eyes bleed (metaphorically).
Perhaps I'm just too old, or lack the training/knowledge of the more recently languages that such features spring up from (Python is usually to blame, imo). It seems I am required to spend more time learning new things than actually building things :/

Perhaps you can help by explaining what your code snippet actually does - in plain old English, I mean - perhaps with some code that uses foo().

Thread Thread
 
bernardbaker profile image
Bernard Baker • Edited

I've put some comments in the snippet I sent you.

I used generators with npm redux-sagas/effects

import { call, put } from "redux-sagas/effects";
// Call requests something
// Put stores something
import Service from "./Sevice";
// Service provides access to API calls
export const foo* = (action) => {
// foo* means it's a generator function
  const data = yield call(Service.getData, action.userId)
  // yield is used to halt execution until a response is provided
  // do something with the data...
  console.log(data.user.last_login_timestamp)
}

You are right though. Developers spend a lot of time learning things. Which it why it's ideal turn on the basics and fundamentals of a particular language that you have interesting using. And then apply a framework to to improve structure and facilitate use cases or business operations or whatever else you need to to implement.

Python is a great language. It run stand-alone as programs from the terminal or in the web or for data science or whatever else you may want to do with it.

And it is hard to understand other people's code sometimes if they don't document clearly.

Code should be understandable just by reading it, if variables and functions are named properly and structured well.

But some developers tend to be quirky and innovative with their coding which can lead to misunderstood implementations or difficult to understand blocks of code. Which leaves the developer working on it with time to learn how it works.

Thread Thread
 
bernardbaker profile image
Bernard Baker • Edited

Found an example of the JSON.stringify() when working with console.log() for an Array.

let data = [1,2,3,4,5,6,7]; // length === 7
console.dir(data); // length === 7. But the actual length is 6.
let obj = data.pop();

Look at the length output by the log. And open the property in the log to see the content and look at its length property which should be 6.

let e = [1,2,3,4,5,6,7]; // length === 7
console.dir(JSON.parse(JSON.stringify(e))); // length === 7
let r = e.pop();
Thread Thread
 
davidmaxwaterman profile image
Max Waterman

So, the calling code does:

var iterator = foo();

var {value, done} = iterator.next(); // call() is executed synchronously and its return value is returned as next().value - next().done is false

iterator.next(); // console.log() executes - this returns {value: undefined, done: true}

IINM, Service.getData just returns a Promise which call() returns, so I'm not sure why you wouldn't simply use async/await:

export const foo = async (action) => {
  const data = await call(Service.getData, action.userId);

  console.log(data.user.last_login_timestamp);
}

I'm thinking all this obfuscation is imposed by the framework you're using, no doubt for good reason, but that's kind of my big beef with such frameworks. I really don't much care for them because they are fragmenting my skillset, not to mention the job market...I no longer am a 'web developer', but am a 'Redux' (or React, or whatever) developer, and the tendency is to forget the underlying platform - I have to essentially throw away what I already know. This means that I am screwed if/when the framework goes away, which they generally do eventually.

I can see value in learning generator functions and iterators, since they are part of the platform and they will surely have a long life. I also value libraries of tools that I can use when I want, but I very much dislike frameworks that swallow everything I do. I am happy to learn things that are likely to become part of the platform.

Re: Python, you've not said anything that isn't also true of javascript, or perl, or any number of scripting languages. I don't have any problem with Python itself, but I dislike that people keep trying to force it, via various tools, into my javascript environment (not to mention the crazy stack dumps it does), when it doesn't really fit and would be much better in javascript in the first place.

frameworklessmovement.org/

Thread Thread
 
bernardbaker profile image
Bernard Baker

It's an implementation of redux-saga. Sagas are implemented using Generator functions.
redux-saga.js.org/docs/basics/Decl...

I've taken onboard that you feel that your skill set is being fragmented and you're no longer a web developer. But isn't part of the journey learning new things. Do you prefer working solely with a language and not using frameworks?

I guess you do because you mentioned that you a developer tends to forget the underlying language implementation, how it works, etc.

Small libraries are very useful. If I remember correctly moment.js is great for handling date formatting and parsing. Due to the irregular nature of the implementations of the Date class.

Re' being screwed if the framework goes away. I looked at your profile and it says that you've mainly been working with JQuery, JS and web technologies. Is that right? What's your go to language for programming on the web.

There's always value in learning something. But in the development domain. That learnt skill needs to be applied. I knew a guy who knew all the buzz words, names of frameworks, some can name it. But he didn't understand basic theory such as data structures and data types.

Re: Re Python, Python is a widely used general-purpose, dynamic, extensible, high-level programming language. ... 'Python is a powerful, opinionated and idiosyncratic (odd) scripting language, loved (and hated) by programmers the world over for its style, syntax and attention to whitespace.

Mad - crazy - stack dumps, not ideal. But I do love a good log.

Why do you feel that Python is being forced? Via various tools? And how is it forced into your JS environment.

when it doesn't really fit and would be much better in javascript in the first place.

What do you mean by this?

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

you're no longer a web developer

Actually, I don't use frameworks (except when I take on a project from someone else), so I don't feel that :) However, I do feel the pressure to do so - almost every job advertised requires React.

But isn't part of the journey learning new things.

Not really. I want to build things, not learn things just for the sake of it - and it seems like most of these frameworks solve the same sorts of problems in different ways, but you kind of have to choose - well, if you want to be employed anyway.

Do you prefer working solely with a language and not using frameworks?

I consider the platform to be "the framework", and prefer to use that.

I guess you do because you mentioned that you a developer tends to forget the underlying language implementation, how it works, etc.

Yeah, just go to SO and see all the solutions that require jquery...it's not a new problem :)

Why do you feel that Python is being forced? Via various tools? And how is it forced into your JS environment.

It's just lack of thought on the part of some tool developers. Developing a tool in python makes it "less easy" to integrate into the suite of tools I already use which are based on javascript/node. I have direct experience of this...and my (er) 'observations' were accepted and they rewrote the tools in node so they were much easier to integrate into (iirc) my gulpfile (or it might even be earlier than that - gruntfile). Don't get me started on built tools...they're way too complicated too.

Thread Thread
 
bernardbaker profile image
Bernard Baker

That's interesting. How did you contribute?

I've used gulp for build automation in the past. I think it solves the problem of having to do it your self. Or maybe that comment is a no trainer because it's clearly stated on the website.

I'm doing a few things today. One of which is a node app which integrates with Google docs. I need a report taken from a database and stored in a Google Doc which can then make use of GSuite features.

I took a look at frameworklessmovement.org it makes sense to use it in some respects. Web components are really good.

So considering you consider the platform to be a framework. What do you define as a platform?

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

What do you define as a platform?

The DOM, mostly...also the three languages, html, css and javascript, in that order.

Thread Thread
 
bernardbaker profile image
Bernard Baker

I never thought as the DOM as a platform. But in further notice that makes sense.

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

Yeah, and it is VERY small and loads really quickly.
Of course, that doesn't apply for node. I'm not sure what the platform is called there...perhaps simply 'node'.

Thread Thread
 
bernardbaker profile image
Bernard Baker

Yeah it's called Node. It provides APIs that allow file system access. You can create servers and more.

Thread Thread
 
davidmaxwaterman profile image
Max Waterman

Yes, I know what node /is/ - I just don't know what they call the 'platform'.
IE, a browser isn't called 'DOM' though that is (I think) what they call it as a platform.