HNHacker News
TopNewBestAskShowJobs

nolanl

1,091 karma · joined August 13, 2013

[ my public key: https://keybase.io/nolanlawson; my proof: https://keybase.io/nolanlawson/sigs/5Udxhb8X1E57tmNkoMyOonOIeiVfEpGPlwm9amgvHMQ ]
submissionscomments
nolanl··on Pokedex.org: a progressive webapp for Pokémon fans
Thanks for the response! Firefox definitely has some speed issues (FirefoxOS included), but I haven't diagnosed it yet. Chrome on Android is the current "best" experience.

As for the back button, yeah, I need to add routing: https://github.com/nolanlawson/pokedex.org/issues/2

nolanl··on React Native for Android
Interestingly, they seem to be using JavaScriptCore instead of V8 as their JavaScript interpreter: https://github.com/facebook/react-native/blob/42eb5464fd8a65...
nolanl··on Apache Cordova: after 10 months, I won't using it anymore
Well, WebSQL was deprecated in favor of IndexedDB. LocalStorage is also quasi-deprecated (synchronous access == problems), which is why it's not available from a worker either.
nolanl··on Apache Cordova: after 10 months, I won't using it anymore
For doing database work in a separate thread, you used to be able to access WebSQL from a web worker on both iOS and Android, but sadly that's been dropped as of Chrome 39 and iOS 9: https://github.com/pouchdb/pouchdb/issues/2806

Also I don't believe you can use the SQLite Plugin in a web worker either: https://github.com/litehelpers/Cordova-sqlite-storage/issues...

Luckily, you can still access IndexedDB from a web worker on both platforms (if you are able to use Safari's partial implementation). Also depending on what kind of work you're doing in the database, most of the action happens at the native level rather than the (DOM-blocking) JS level.

nolanl··on Safari is the new IE 2: Revenge of the Linkbait
Wow, HN commenters are brutal! :) I thought the title captured the spirit of the piece; the problem was that people shared it without discussing the contents. As if to say, "Welp, that's it: Safari is the new IE. After all, some dude said it!"
nolanl··on Safari is the new IE
I still have a soft spot for WebSQL over IndexedDB - way easier to work with, incredibly powerful, brought the speed and reliability of SQLite. However, WebSQL only ever managed to have one implementation (Chrome and Safari shared WebKit at the time), and the other vendors besides Opera didn't want to touch it. So it's long since time to accept that it's dead.

What bothered me most about the IndexedDB fiasco with iOS8 is that Apple not only held out for so many years, but then they deployed a broken implementation. Anybody who had written an app using an IndexedDB shim either had a crashed site at best or lost user data at worst. YDN-DB author Kyaw Tun had the best quote: "I don't understand how they can release this."

Whether you like an API or not, a browser vendor should at least release it in good faith if they're going to release it.

nolanl··on Safari is the new IE
Nope, people literally did say things like "a certain company in California." But yeah, I'm exaggerating a bit, because the name "Apple" did come up occasionally.

The problem is that when everybody wants to discuss the hot new browser features, mentioning Apple is just a big downer. We all know we're going to have to polyfill at best, or just not support Safari at worst. Nobody wants to be reminded of that sad fact when you're trying to get excited about the potential of the web platform.

nolanl··on Safari is the new IE
Yep, I have had to support IE7 and 8. IE6 was, thankfully, a bit before my time.

And yeah, the title is pretty clickbaity; guilty as charged! But my blog has no ads, so it's not like I'm making money off of it. I'm just trying to draw attention to what I think is an important issue.

As others have pointed out, it's all a matter of perspective. If you're trying to build for Web 2.0, then Safari is a fine browser. But if you're trying to build for Web 3.0 (or the "next web" or "appy web" or whatever you want to call it), then prepare to be disappointed.

nolanl··on Firefox OS on Android Devices
You can dual-boot FXOS and Android using MultiROM. I wrote some instructions for Nexus 5 here: https://github.com/nolanlawson/nexus-5-triple-play#readme
nolanl··on We have a problem with promises
Yep, Chrome is pretty great about printing unhandled promise rejections to the console. However, I just tested Firefox and Safari, and neither of them will warn you in that case - not to mention older browsers like Android <4.4 and IE <=11, which don't even have native promises!

So if you're ever trying to debug promises in a non-Chrome browser, you may find my "insane" advice pretty helpful. :)

nolanl··on We have a problem with promises
I've got my hands pretty full with Pouch, but I'll take a look! :) Thanks.
nolanl··on We have a problem with promises
That's a fair point, but I think the name itself ("await") tends to communicate the the operation might take a long time. Compare that to multithreaded languages like Java, where it's not obvious that FileInputStream/HttpClient/etc. could take a long time!

Anyway, the big benefit of async/await, to me, is that you really DON'T have to understand promises. :) For instance, at some point we will probably add ES7 examples to the PouchDB API docs (e.g. here: http://pouchdb.com/api.html#create_document), and you can imagine that, from the user's perspective, the word "await" will just be part of the API (e.g. `var doc = await db.get('id')`), and beyond that, they won't have to learn anything about promises or async or callbacks or any of that.

nolanl··on We have a problem with promises
Those new warnings are FANTASTIC.

That's exactly what I meant when I said it's better for your tools to warn you, rather than trying to read and understand some lengthy article. :)

BTW for PouchDB, we use bluebird in Node and lie in the browser, and bluebird has been truly indispensable for debugging. Looking forward to it getting even better!

nolanl··on We have a problem with promises
Yes, but in most code I've seen, that's a typo rather than someone intentionally writing a function that returns a function. You can definitely do it!
nolanl··on We have a problem with promises
This is what I mean:

  doSomething(function (err) {
    doSomethingElse(function (err) {
      doYetAnotherThing(function (err) {
        throw new Error(
          "I don't bubble up to the top of the stack, " + 
          "because there is no stack!");
      });
    });
  });
BTW a great trick is to tick the little "Async" box in the Chrome Dev Tools, so you can get a full stacktrace showing exactly where you came from. It works for both callbacks and promises: http://www.html5rocks.com/en/tutorials/developertools/async-...
nolanl··on We have a problem with promises
You're right; I'm playing a bit fast and loose with the definition of "equivalent." However, I think it's what most people want when they reach for the forEach().

In that "Promise protips" gist (https://gist.github.com/nolanlawson/6ce81186421d2fa109a4), I have an example of something closer to what you describe: the sequentialize() function will execute one promise after the other, and fail as soon as a single one fails.

However, if you need to actually run multiple promises in parallel, but cancel them as soon as a single one fails, then you might want something more advanced than promises, like RactiveJS (https://github.com/ractivejs/ractive) or RxJS (https://github.com/Reactive-Extensions/RxJS).

nolanl··on We have a problem with promises

  naivePromiseAPI() {
    if (foo) {
      throw new Error('this will get swallowed!');
    }
    return somePromise();
  }
Instead you want this:

  cleverPromiseAPI() {
    return Promise.resolve().then(function () {
      if (foo) {
        throw new Error('this won't get swallowed!');
      }
      return somePromise();
    });
  }
Because if the client of the API does something like this:

  $('.my-button').on('click', function () {
    cleverPromiseAPI().catch(console.log.bind(console));
  });

Then the client might expect the error to get console.logged, but actually it won't in the naive case. That's because the error was thrown synchronously and thus bubbled up to the click handler, instead of being caught inside of the promise chain.
nolanl··on We have a problem with promises
If anyone's confused by the 4 "puzzles," I whipped up a JSBin to demonstrate: http://jsbin.com/tuqukakawo/1/edit?js,console,output
nolanl··on We have a problem with promises
Bluebird is awesome. :) I especially love promisifyAll() and promisify().

The only reason I didn't include something like that in the post is that I didn't want to overwhelm newbies. I think it's already confusing enough what the difference is between q/when/RSVP/bluebird/jQuery promises/Angular promises, etc... And honestly, more and more I just use vanilla promises, or a tiny polyfill like Lie.

nolanl··on We have a problem with promises
Very true. And as I mention in the article, ES7 async/await should help fix that: http://pouchdb.com/2015/03/05/taming-the-async-beast-with-es...
nolanl··on The state of binary data in the browser
Sorry, my bad. It's Chrome, Safari, and IE that don't have toBlob(). I'll fix the post.
nolanl··on Show HN: Jison Debugger – A visual editor for JavaScript parsers and lexers
That would be my #1 desired feature to add to this app - syntax highlighting for the Jison grammar.

Since CoffeeScript and Handlebars are written in Jison, you'd think someone would have done this already, but I couldn't wrap my head around the Ace highlighter implementation for those languages. It didn't seem to be as simple as "plug in this Jison grammar and get a highlighter." If that were the case, it would be easy, because Jison itself is written in Jison. :)

nolanl··on Taming the asynchronous beast with ES7
I agree that a purely blocking style would be best, and maybe we can hope for that in ES8. :) But async functions are still much nicer than promises.

And in practice, I don't think it will be that hard to explain to newbie programmers. Most of them will not be writing code that actually produces promises, just the code that consumes it (because they're not writing ajax/database libraries). So the "await" basically becomes part of the library API from their perspective.

E.g. they type "await library.doSomething()", their editor tells them that the surrounding function needs to be async, so they add the word "async," and they're done. They don't have to learn a completely new system in order to work with this library.

As for the uncaught Promise rejection project, it is certainly nasty (and has burned me many times as I worked on Pouch), but I'm hoping this can be solved by better tools. E.g. in Chrome, they recently started logging uncaught promise rejections to the console.

nolanl··on Taming the asynchronous beast with ES7
My main point was that promises represent an entirely new coding style, which pantomimes the familiar try/catch/return, but isn't quite the same. So you have to learn two systems.

For instance, the following three blocks are not equivalent, but they're easy to mix up:

  // executes serially
  promise.then(function () {
    return somethingThatReturnsAPromise();
  }).then(...)
  
  // doesn't wait for something() to return
  promise.then(function () {
    somethingThatReturnsAPromise();
  }).then(...)
  
  // executes something() immediately
  promise.then(somethingThatReturnsAPromise()).then(...)
With synchronous code, it's obvious what order things happen in, because you just read top to bottom. But yeah, I do agree that arrow functions make it a bit nicer. :)
nolanl··on ForerunnerDB – Lightweight JavaScript Database with Persistence and Data-Binding
Unfortunately, support is still not great: http://caniuse.com/#feat=indexeddb

Those yellows are really more yellow than green, in my experience. :/

nolanl··on ForerunnerDB – Lightweight JavaScript Database with Persistence and Data-Binding
LocalForage has great cross-browser support (automatically switches between IndexedDB/WebSQL/LocalStorage), not to mention workarounds for browser bugs and the ability to store more data than what LocalStorage allows (~5-10MB). It seems like a fairly non-trivial component.

I just think it's nice to give a little credit where credit is due. :) I do see that you mention LocalForage in the changelog, but a shout-out on the site would be cool as well.

For my own part, PouchDB is pretty heavily based on LevelUP (in Node.js anyway), so we're sure to document it on the website: http://pouchdb.com/adapters.html#pouchdb_in_node_js

nolanl··on How to be a good open-source citizen
Totally agree. I could write an even-longer essay on "How to be a good open-source maintainer."

Too many projects have poor documentation/tests, or they don't make it clear how to contribute. Something as simple as a CONTRIBUTING.md file can be really valuable; IRC and mailing lists are also good resources to offer.

nolanl··on ForerunnerDB – Lightweight JavaScript Database with Persistence and Data-Binding
Under the hood, it seems [1] to be based on the excellent LocalForage project from Mozilla [2]. It would be nice to acknowledge that on the website somewhere.

[1]: https://github.com/Irrelon/ForerunnerDB/blob/master/package....

[2]: https://github.com/mozilla/localForage

nolanl··on Wiki creator reinvents collaboration, again
There actually is a PouchDB Node server already: https://github.com/pouchdb/pouchdb-server/. Installing it is as easy as `npm install -g pouchdb-server`

Also, Drupal recently announced that they're going to offer a CouchDB-compatible server. So yeah, anybody can implement the sync protocol. :) http://wearepropeople.com/blog/a-content-staging-solution-fo...

nolanl··on Statements about the Mobile Web
The WKWebView is buggy/breaking enough that the Cordova team has still not integrated it: https://shazronatadobe.wordpress.com/2014/09/18/cordova-ios-...
← PreviousPage 3 of 4Next →