Fork me on GitHub
#clojurescript
<
2019-04-16
>
misha13:04:19

greetings! what can/should I do to import {_esModule: true} with shadow-cljs? strange thing is: it worked few minutes ago, but after some reloads and extra deps - it broke, and all I can see is in chrome console is:

(ns slate
  (:require ["slate" :as slate]))

(js/console.log slate)
;; {_esModule: true} with an Object prototype methods.
cleaning target and recompile anew did not help.

misha14:04:10

omfg this was the reason: https://github.com/thheller/shadow-cljs/pull/480/commits/2f56f7499ec9e1a16ea6d63c4c19ce8485e1de81 not sure though how it worked w/o utf-8 in the first place (created a project from this "template" https://github.com/minimal-xyz/minimal-shadow-cljs-browser linked to from the http://shadow-cljs.org/ home page)

thheller14:04:12

@misha FWIW __esModule is just a marker property created by babel to indicate that the source was an ES module converted to CommonJS

thheller14:04:41

that isn't related to the utf-8 at all though

misha14:04:55

I know, but imports were working (even with Uncaught SyntaxError: Invalid regular expression error from PR), but then broke, and broke in random way every time I cleaned up and rebuilt

misha14:04:03

(I know I know, you cannot rely on anything in JS after 1st error in console, but it did work for tens of minutes at first)

misha14:04:20

and since template project's index.html is just <div><script></script></div> - it screwed me over

ag18:04:33

can someone tell me how to get “user stops typing” thingy? why this doesn’t work as expected:

(defn- on-key-up [ev]
  (.persist ev)
  (go
    (<! (timeout 1000))
    (js/console.log "sending request for:" (.-target .-value ev))))
If I type “help”, it waits for a second but shows “sending request” 4 times. I want to wait for user to stop typing and then send a single request

lilactown18:04:17

seems correct. on each key up, it creates a channel and times out for 1000ms

mccraigmccraig18:04:20

you are running a separate timeout for each on-key-up event

lilactown18:04:00

what you actually want is to debounce it

Björn Ebbinghaus18:04:24

You could use alts! to wait for a new key or the timeout. alts! returns the matched channel. if timeout -> send reques

ag18:04:00

can someone show me a snippet that works… using goog.async.Debouncer - I’m still seeing multiple messages in the console

ag18:04:23

it does it after the given interval, but does it multiple times

lilactown18:04:34

what's your updated code

ag18:04:01

(defn debounce [f interval]
  (let [dbnc (Debouncer. f interval)]
    ;; We use apply here to support functions of various arities
    (fn [& args] (.apply (.-fire dbnc) dbnc (to-array args)))))

(defn- on-key-up [ev]
  (.persist ev)
  (let [dfn (debounce #(js/console.log "sending request for:" (utils/target-val ev)) 1000)]
    (dfn)))

lilactown18:04:22

that creates a new debounced function everytime

ag18:04:34

how do I pass value into debounced fn then?

lilactown18:04:59

the function can take any argument

lilactown18:04:35

read the article I posted

lilactown18:04:48

I also posted an example using goog.functions/debounce

ag18:04:58

I need to pass value to the listener

lilactown18:04:40

I don't understand what you mean

lilactown18:04:35

(ns my-app
  (:require [goog.functions :as gfn]))

(def send-req! 
  (gfn/debounce 
    (fn [ev] (js/console.log "sending request for:" (-> ev .-target .-value))
    1000))

(defn- on-key-up [ev]
  (.persist ev)
  (send-req! ev))

ag18:04:06

even this example prints multiple times in the console

ag18:04:22

you type aaa it would do a aa aaa

ag18:04:43

I need to send request once

ag18:04:36

this is so trivial to get it right with rxjs or similar, it makes me mad I can’t get it work

lilactown18:04:30

hm, it seems to only debounce in the same tick

ag18:04:03

¯\(ツ)

ag18:04:52

I guess I’m gonna try plain-old setTimeout/clearTimeout but I’ll have to store the timeout somewhere. I guess I’ll store it in an atom…

ag18:04:23

doh… this is so… inelegant

ag19:04:48

(def last-timeout (atom nil))

(defn- on-key-up [ev]
  (js/clearTimeout @last-timeout)
  (.persist ev)
  (reset!
   last-timeout
   (js/setTimeout
    #(js/console.log "sending request: " (utils/target-val ev))
    1000)))

ag19:04:08

any gotchas?

lilactown19:04:09

I think that has the same problem

lilactown19:04:31

it's going to run setTimeout as many times as you press the key

ag19:04:25

it sets timeout for the last thing… it fires after a second… it prints exactly one thing

ag19:04:29

that’s what I need

lilactown19:04:53

no, it sets the timeout each time you press a key 🙂 not the last thing

ag19:04:30

yeah, but it clears previous timeout every time

ag19:04:36

what’s the problem?

lilactown19:04:06

ah I wasn't reading it right

ag19:04:59

but I hate it… it stupid… and … it works

ag19:04:38

I’m sure there are some gotchas that I’ll discover later

lilactown19:04:52

I'm still really confused by goog.functions.debounce not working as I expect it

ag19:04:05

yeah me too

lilactown19:04:52

I wonder if it's because I'm testing it from a node REPL?

ag19:04:11

I dunno… I’m doing it in figwheel

lilactown19:04:31

(do (send-req! "foo") (send-req! "bar")) only fires "foo". but (send-req! "foo") (send-req! "bar") fires it for "foo" and "bar"

ag19:04:01

anyway… thanks a lot for your help Will!

misha19:04:30

@ag @lilactown send-req! creates new anonymous fn on each call. def it first.

lilactown19:04:14

that is not what I would expect

misha19:04:01

actually, scratch that, I thought it is defn, but it is def.

misha19:04:17

I had the same behavior before, when I gave goog.functions.debounce new fn on each call.

jsa-aerial22:04:13

@mfikes I've been trying to get self hosted Cljs to recognize 'ambient' functions in a precompiled library. Using the functions directly from Cljs (via figwheel and cljs-repl) works just fine. I've also read https://stackoverflow.com/questions/51573858/how-can-i-run-eval-in-clojurescript-with-access-to-the-namespace-that-is-calling/51575204#51575204 and https://stackoverflow.com/questions/50828008/how-can-i-make-functions-available-to-clojurescripts-eval. Those are somewhat enlightening but kind of opaque as well. In any event, when I try the technique outlined in the former, what I currently run into is env/compiler is nil instead of an atom with something in it. However, I am trying to call the cljs.js/load-analysis-cache! directly, not via a macro. Any ideas/insights most appreciated.

jsa-aerial22:04:42

@mfikes second question : If the 'ambient' library is compiled with advanced optimization, can it be used in a self hosted client. I know that the client can only be compiled with 'simple' optimization, but I am wondering about the library.

mfikes22:04:54

@jsa-aerial If you use cljs.js then env/*compiler* is bound for you. Are you experiencing a nil value when using the ambient project?

jsa-aerial22:04:25

I'm just requiring cljs.js and cljs.env

mfikes22:04:45

@jsa-aerial It would be odd to have a mixture of :advanced and :simple running in the same JavaScript engine. But in theory if you managed to load an :advanced version of the ambient library in, you'd at least need to mark the my-inc function with ^:export

mfikes22:04:13

For the nil env/*compiler* you'll probably have to provide a minimal repro to make any sense of that—in other words, would need to know the exact setup you're running through to cause that

jsa-aerial22:04:16

Hmmmm, the library is one that is built and available as an artifact.

jsa-aerial22:04:57

OK, I need to go now, but will try to put something together that shows what I am experiencing.

jsa-aerial22:04:15

Maybe it has something to do with the order things are required?

mfikes22:04:03

Well, env/*compiler* is a dynamic var that gets bound when you call certain functions in cljs.js

jsa-aerial22:04:55

You have to call something in cljs.js before env/*compiler* is initialized?

jsa-aerial22:04:00

what would that be?

mfikes22:04:02

Oh, I'm re-reading that SO. There are two env/*compiler* instances at play. So, just need to know exactly what you are doing.

jsa-aerial15:04:41

OK, I think have this mostly figured out. I'm now guessing that the two env/*compiler* instances are, one in the JVM and one in the JS (browser). Then some 'magic' happens where when evaluating cljs.js/load-analysis-cache! in the browser communicates with the JVM side and retrieves its env/*compiler* data and puts it the JS env/*compiler* state.

jsa-aerial15:04:43

@mfikes ^^^^ Also, interestingly enough, I can call the advanced optimized functions of the ambient lib(??)

jsa-aerial15:04:59

I guess the last question I have now is - how would you go about achieving this in a build? Right now, I'm just evaluating the load-analysis-cache! in the repl