This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-09-29
Channels
- # ai (2)
- # beginners (12)
- # bitcoin (1)
- # boot (41)
- # chestnut (5)
- # cider (9)
- # clara (24)
- # cljs-dev (11)
- # clojure (107)
- # clojure-dev (2)
- # clojure-italy (4)
- # clojure-nl (4)
- # clojure-russia (10)
- # clojure-spec (19)
- # clojure-uk (71)
- # clojurescript (121)
- # cursive (3)
- # data-science (7)
- # datacrypt (1)
- # datomic (72)
- # docs (7)
- # duct (2)
- # emacs (3)
- # ethereum (1)
- # figwheel (1)
- # fulcro (58)
- # graphql (16)
- # hoplon (9)
- # jobs (2)
- # jobs-rus (1)
- # lein-figwheel (1)
- # leiningen (25)
- # luminus (2)
- # lumo (5)
- # off-topic (6)
- # onyx (22)
- # pedestal (3)
- # portkey (1)
- # proton (2)
- # re-frame (7)
- # remote-jobs (1)
- # ring-swagger (3)
- # rum (2)
- # shadow-cljs (38)
- # specter (7)
- # yada (30)
Hi all, has anyone here tried to use re-captcha in a CLJS project ?
Hi ! I did and it works quite well. First I included the re-captcha script tag in my index.html
. I'm using reagent, so I made a function called re-captcha
that I call in the :component-did-mount
callback
(s/fdef re-captcha
:args (s/cat :dom-id string?
:callback ifn?))
(defn re-captcha
"Display a google re-captcha securer"
[dom-id callback]
(.render js/grecaptcha dom-id
#js {:sitekey (:recaptcha_client_key (get-env)) ;"6Lec_hEUAAAAALbHlhuwhunfF3RAu6kabEz5qaV2"
:callback callback}))
(defn reset-captcha!
([]
(reset-captcha! nil))
([captcha-id]
(if captcha-id
(.reset js/grecaptcha captcha-id)
(.reset js/grecaptcha))))
You might notice I have a function called get-env
, it returns a map of environnement variables. This way I have a different re-captcha siteKey in dev, test and prod.
hi @U2DART3HA that worked / thanks very much!
@lilactown https://stackoverflow.com/questions/39291779/idiomatic-conversion-of-node-js-apis-to-clojurescript
@lilactown @yury.solovyov I wouldn't jump to using core.async without compelling reasons. Promises are pleasant to use from cljs, and they're easily available in node
in addition to @pesterhazy , I've found that I like reqctive-atoms much much more than core.async: reactive-atoms = think about relationships, core.asyc = think about processes, and reactive-atoms gives better stack traces too
@qqq, are you talking about reagent's ratoms? OP's context was using Node.js apis I think
@pesterhazy: yes, reagent ratoms, I'm pretty sure they can be used without gui; though perhaps I misunderstood OP's question
you probably can but I doubt it's a good idea...
why not? I really like the idea of functional reactive programming / specifying a graph of "when this updates, update these other things too" -- it's like spreadsheets -- I find it far more declarative / easier to reason about than core-async
ratoms are intended to used in react render functions. Maybe a similar but more general-purpose abstraction could be built but AFAICS ratoms are not that
actually, I thought r-atoms just did some black amgic to keep track what the given atom derefs, then addas watcher to the derefed atoms to auto update
Not sure if it is the appropriate place to ask the question here, but I just couldn't figure out how to make it work with rum... https://github.com/clauderic/react-sortable-hoc/blob/master/examples/basic.js
I guess there're alternatives to ratoms for doing reactive computations, e.g. freactive.core
. I compiled a list of similar libs a while ago here: https://metametadata.github.io/carry/faq/#is-there-a-way-to-code-a-view-model-if-i-dont-use-reagent
Although using ratoms or the like as alternative to core.async and promises sounds interesting, I wonder how to deal with error handling then? Promises have the built-in notion of errors and for core.async smt. like <?
macro can be used. cc @qqq @pesterhazy @lilactown
I'm increasingly convinced that Promises are officially a Good Idea[TM] and work really well with ClojureScript
agree. had to interact with firebase which is all promise based. quite nice actually
It was OK working with promises in JS, but I bit the bullet and went directly to using core.async
with <?
macro in CLJS. I like that I can use built-in try-catch-finally
to handle errors instead of the DSL and code reads almost as usual synchronous one (syntactically it looks quite similar to JS code with async
/`await`).
i have promise-based cljs code reading almost like synchronous code @metametadata π
To me core.async in CLJS has drawbacks. Extra dependency, doesn't work great in bootstrapped cljs (lumo), channel abstraction not ideal to just chain async computations (main use case), macros are not composable
The fact that it covers both cljs and clj has its cost - it core.async may be better for clojure, but for cljs it's often (not always!) overkill
@mccraigmccraig do you use some kind of library? promesa I guess?
Promises by contrast are just functions π
here - using one of the promise-based js fs apis - with promesa+cats @metametadata - https://gist.github.com/mccraigmccraig/a8fe17eb500b231e8cc949bb74adb49f
@pesterhazy In Lumo I use deasync
and make all my code literally synchronous π
@metametadata what is this magic?
I guess it's written in C
works nicely for my shell scripting needs as I don't really want to coordinate anything asynchronous and just execute commands in sequence
ever since i realised that my utility scripts often end up being bundled up into api-side functions i started to write everything async and focused on ways of making async as easy as possible to write/grok
@mccraigmccraig same for me - you start off goofing around synchronously-ish but eventually it'll end up in your code
personally I find that channels are a much better abstraction as soon as I want more than one value over time
however, I've realized after writing it in channels that I actually don't need that functionality π wishing I had gone with promises now
especially given the overhead of core.async and compiled cljs vs. using a lumo script
I rolled with just using lein's figwheel-node
template for a simple command line app and the bundle is 1.5mb. can't use advanced optimizations because I used core.async too π
@lilactown FWIW you can run your Lumo script with -K
and subsequent runs will be faster (core async compilation will be cached)
for comparison, here's how my core.async/<? code looks like: https://gist.github.com/metametadata/bb31af03c9949b3518ed2f94f3c84ce3
@lilactown for CLI apps I would really recommend deasync
-ing async functions if in nature your code is sequential
aah, ok then π
@metametadata i'm gonna use that gist as a reference for error handling in my app π
sure, you're welcome. you'll need to find some implementation of <? though. we hand-rolled our own but it's not open-sourced yet
no, cats
is what promesa
uses as far as I understood
promesa
doesn't use cats
, but cats
has a promise-monad implementation for promesa
just sayin' - promises give you error handling as well
@qqq βitβs like spreadsheetsβ Great, isnβt it? I ported my reactive Cells library from CL to CLJ/CLJS (re-christened Matrix) and started on a web framework but am just starting on the doc. I have a TodoFRP treatment here: https://github.com/kennytilton/todoFRP/blob/matrixjs/todo/MatrixCLJS/README.md A lot of that is still a copy/paste from the sister JS version ../MatrixJS. Ping me if you have Qs at kentilton at gmail.
is it possible to wait for promise by de-refing it in cljs?
(let [value @promise])
@yury.solovyov no, because Javascript is single-threaded
I meant is it possible to make js promises feel the same way?
yes, for example with core.async, the go
macro will rewrite your linear-looking code to be callbacks under the hood
I know it is possible with core.async (I really need to write questions better), but what I'm trying to get into, is I want to be able to use js promises as in clojure or in go blocks, but with all that stuff hidden from me
maybe it is possible to implement new kind of promises that wrap native js ones and "wait" on deref?
with whatever is needed under the hood
@yury.solovyov I'm not aware of any experimental work being done in that area
@yury.solovyov no, not possible. due to the async nature. once you go async everything has to be async.
just like the async
keyword in JS, if you use it once you have to use it everywhere basically π
but in cljs go is basically free, right?
well, that's fair, thanks
btw. I tend to view core.async as generalization of promises, they can be called multiple times and yield a stream of values instead of one
so the conversion promises -> channels is quite clear, the other way must introduce some strong assumptions
also error handling / exceptions problem is quite blurry in my mind - depends on situation
I kinda wish I had to deal with less channel passing all over the place
try to design core of your app to be synchronous data-in -> data-out, and then wrap it on the edges with async stuff
that's what I did, but the async part still need some love w.r.t. generality
I think Tim covered some of the ideas how to "hide" async parts of your app here in this talk:
it takes a while to "see" these places tho
and then to come up with an elegant replacement
I'm not complaining, it just takes time to develop these senses
yes, instead of working with channels directly, you should be building transducers (still sync code) and glue all together at the edge of your app (where you be async)
yup, I even have a TODO with "transducer here?" π
https://github.com/YurySolovyov/eion/pull/17/files#diff-584f3c2948116a881b7717bb0529a24fR160
think about transducers as functions which do not work with input and output data structures directly, they are abstracted from it
so instead of threading a data through a set of functions to transform it, you first compose transducers of those transformations and get a composed transducer back, and then use some machinery to put transducer, input data structure and output data structure together to get the same result
but they have to be sync, right?
so then you need to pipe some channels or something
if there is some asynchrony associated with input or output, you are not affected by it when working on transducers
well, what if to know the next value, I need to call an async thing?
pretend that you have it π and some machinery which will be composing your code at the edge of your app will wire it with async stuff π
but this is getting too abstract, it is not always easy, transducers or function composition is just a tool
ok, now I don't get it, how can I pretend? say I'm reducing a channel with sum of values, to get the next value I need to call something async. how do I pretend?
ok, maybe it is too abstract
In your example I was concerned about the function +
, that is syncronous and does not need to be involved in async ops, reduction over a channel is that machinery happening at the edge of your app
the question is how can you restructure your code which is a chain of async ops to be a chain of synchronous operations which get assembled by something at "outer" level and that something knows how to do async/await
I get it when people say that I need to move async stuff to "the edge of your app", but it is too hard to act on, like I still need to build that part, even on the edge of my app, and for some reason nobody talks about it π
ok, I'll re-watch it cause I've seen it, but probably missed something the first time
Still thanks for a chat