1. 8

    Last week I shared forgo: a light-weight 4kb React alternative which encourages using plain JS and DOM APIs. https://forgojs.org

    Plan for this week:

    • Add more tests
    • Add support for fragments
    1. 2

      Awesome, thanks for sharing. Will definitely keep an eye on this.

    1. 1

      I haven’t delved too deep but this seems like GraphQL in a way.

      1. 1

        It can aggregate like GraphQL, but other features (like circuit breakers, web sockets, load balancing etc) aren’t covered by GraphQL. This is more like Ocelot, but simpler: http://threemammals.com/ocelot

        But your comment is puttng some ideas in my head; maybe GraphQL support is a feature I could add?

        1. 1

          I’m a fan of it, so why not? (:

      1. 1

        Hi, I’ve been working on this for the past three months. I started this project because many clients I work with (as part of my consulting gigs) have switched to Micro Services and needed an API gateway in front of them (to do response aggregation, rate limiting etc). There are options out there like Kong, but some of them prefer a simpler (and free) tool extensible using JS. Hence Prism.

        Aside of regular API gateway features, some capabilities in Prism are unique. For instance, Prism can receive messages on Redis channels and forward them to specific WebSocket clients. This allows multiple services to asynchronously send messages to WebSocket clients.

        Prism is in Beta, but good enough to start trialing with. Over the next few weeks, I plan to add more tests and improve the documentation. In particular, the documentation around WebSockets needs more attention.

        Happy to handhold anyone who wants to try Retransmit. If you run into problems, please file an issue on github.

        1. 1

          Babashka is a similar idea for Clojure where you can do stuff like:

          ls | bb -i '(take 2 *input*)' | bb '(first *input*)'
          bb '(vec (dedupe *input*))' <<< '[1 1 1 1 2]'
          
          1. 2

            Thats nice, thanks. Checking it out.

          1. 2

            A nice idea, but if I’m going to go beyond the realm of the script of the shell I’m using, and pipe in and out of a fuller language, I’d turn to Ruby.

            1. 2

              Thanks. Ruby is nice too. This is for the JS programmers out there. Also, for all its drawbacks npm has a module for pretty much everything.

              Add: I think the strength of basho is in how it lets you write and chain expressions with minimal typing. If you used node instead, you could achieve some (not all) of the same things; but with a lot of additional keystrokes.

            1. 4
              1. I finished the website for basho - which lets you to write complex shell tasks using plain JavaScript. It’s at https://bashojs.org

              2. Started a company and launching its first product tomorrow. It’s an API gateway written in Node + TypeScript. The website is WIP, but it can still give you an idea https://retransmit.io/

              1. 1

                Bash looks really cool, I may have to give it a shot.

              1. 1

                Since I’m more comfortable in Python than JS, when bash gets hairy I tend to switch to Python and use the subprocess module to invoke commands.

                Is there a standard way to invoke shell commands from within “normal” Javascript (e.g. whatever node.js uses)?

                1. 2

                  There’s exec and spawn which can be used from JS/node to execute a shell command. Alternatively, you can run JS from the shell with the -e option in node.

                1. 1

                  The reason node doesn’t worry about callbacks is because the issue is going away with ES6 generators. This will be available in 0.12 with the –harmony flag; or you can just use the latest 0.11 unstable.

                  Promises work only in a limited number of scenarios and gets ugly pretty quickly; a fairly common use case:

                  function authenticate() {
                      return getUsername()
                      .then(function (username) {
                          return getUser(username);
                      })
                      // chained because we will not need the user name in the next event
                      .then(function (user) {
                          return getPassword()
                          // nested because we need both user and password next
                          .then(function (password) {
                              if (user.passwordHash !== hash(password)) {
                                  throw new Error("Can't authenticate");
                              }
                          });
                      });
                  }
                  

                  The problem of callbacks in JS cannot be solved in a library. So they’ve has done the right thing; fix it in the language itself.

                  1. 3

                    What can’t it be solved in a library? This is how it’s solved in Haskell and Scala, for example.

                    1. 1

                      Haskell has built in support for monads. And works well with async code. Also see computation expressions in F#. Scala seems to be still debating how to best do async. But they have more tools to attack the problem than JS had.

                      1. 3

                        What does built-in support mean? If it’s the do-notation, then that’s just syntax, which Scala has (not quite as good, but still). I’m not sure if async in Scala is being debated - you either use scala.concurrent.Future or scalaz.concurrent.Task.

                        So I don’t see why JavaScript could not solve it as a library - even if it’s not as capable of abstraction, the “built-in support” seems to be just syntax.

                        1. 1

                          I have rewritten the code in my first comment using generators, which IMO is cleaner than the one with promises. You can convince me with the Scala equivalent of this:

                          function authenticate() {
                              username = yield getUsername();
                              user = yield getUser(username);
                              password = yield getPassword();
                              if (user.passwordHash !== hash(password))
                                  throw new Error("Can't authenticate!");
                          }
                          
                          1. 1

                            The Scala I write avoids exceptions, so it’d be something like this:

                            def authenticate: Future[Boolean] = for {
                              username <- getUsername
                              user <- getUser(username)
                              password <- getPassword
                            } yield user.passwordHash != hash(password)
                            

                            But you’re able to throw an exception, if you really want. Also, the type-signature could be inferred.

                            1. 1

                              So will getUser() take a string, as it should? I am not able to tell how execution will suspend at: user <- getUser(username)

                              Forgive my inexperience with Scala.

                              1. 2

                                The type of getUser is String => Future[User] or something similar.

                                1. 1

                                  Similar to the do notation. I was saying that this needs to be solved in the language. You are relying on language support to turn it into a callback pyramid; actually the other way around.

                                  Add: Two ways you could do this. State machines or like you showed above. You need language support for both these things.

                                  1. 2

                                    Yes, the problem with Callback Hell is not a syntactic one, though.

                                    1. 1

                                      Lack of support for the expressiveness demonstrated above is not a syntactic difference.

                                      clarifying: I was saying that this requires support in the language. Your example and my example demonstrates the same thing.

                                      1. 2

                                        While I absolutely agree that JavaScript lacks Scala’s expressive power, what was demonstrated above which is missing?

                                        Here’s the desugared version:

                                        def authenticate =
                                          getUsername.flatMap { username =>
                                            getUser(username).flatMap { user =>
                                              getPassword.map { password =>
                                                user.passwordHash != hash(password)
                                              }
                                            }
                                          }
                                        

                                        JavaScript has lambdas, what else does it need?

                                        1. 1

                                          This is the callback pyramid that JS users fear; it becomes a problem real quick.

                                          Example, which doesn’t work without extracting ‘….’ into another function and passing it into getAmazonMinOrder():

                                          if seller == 'amazon'
                                              get minOrder via async getAmazonMinOrder()
                                          else
                                              minOrder = 100
                                          .... 
                                          ....
                                          

                                          Hope the example is clear enough. I am going to head out for a bit. Will reply once I’m back.

                                          1. 2

                                            This is one of the reasons why promises/futures are not callback hell:

                                            val minOrder: Future[Int] =
                                              if (seller == 'amazon')
                                                getAmazonMinOrder
                                              else
                                                Future { 100 }
                                            

                                            We’re working with values, not side-effects. It’s possible to abstract and reuse values.

                                            1. 2

                                              I gave you a poor example (and left), I should have used the earlier example itself.

                                              What made your Scala example easy to write is the for comprehension. For a JS version of the same thing, the first snippet I posted is how it looks. The limitation of Promises (in JS) is evident in that example; you get only the last value inside the then() function. The callback pyramid is avoided only in the simpler cases.

                                              I think we are mostly on the same page. The difference is that you use a language in which promises aren’t painful to write, which (probably) shaped your opinion.

                                              bct posts a link below, which proposes a solution in JS. The author of that article calls it ‘then hell’.

                                2. 1

                                  Execution does not suspend. It’s creating a Future value.

                            2. 1

                              I’m not sure if async in Scala is being debated

                              1. 1

                                Neither of those are used or taken past a few experiments.

                        2. 1

                          This is an interesting proposal for avoiding that situation.

                          Basically: Accept promises as function arguments. Then your example becomes:

                          function(authenticate) {
                            var userNameP = getUsername();
                          
                            var userP = getUser(userNameP);
                          
                            $.when(userP, getPassword(userP)).then(function(user, password) {
                               if (user.passwordHash !== hash(password)) {
                                  throw new Error("Can't authenticate");
                               }
                            });
                          }
                          

                          You probably want the getX functions to accept non-promise arguments too, so some of the complexity is just moved, but I suspect a library can hide most of it.

                          1. 2

                            getUser() taking a promise instead of a string is not semantic. We are going to have to ask the question for every function we write; whether it needs to take a promise or a value.

                            1. 1

                              In the slides I linked he solves with a library that wraps functions so they can accept either a promise or a value.

                              I don’t know if it’s a good idea, but it’s an interesting one.

                        1. 2

                          Two weeks to launch an app I’ve been working on over the past year. It lets people define “database tables” and build communities around it. Why would anyone use this? Because many apps such as Flickr, Pinterest are communities around various types of information. Essentially a “Forum platform”.

                          Screenshots: http://imgur.com/a/agRne

                          Code: https://github.com/jeswin/fora/