Home / Blog / Hardware
Hardware วิเคราะห์จากสเปค + รีวิว

Analysis and Review: ClojureScript Gets Async/Await

Analysis and review of adding Async/Await features in ClojureScript that will make writing asynchronous code easier

ClojureScript Gets Updated with async/await Support

ClojureScript has added async/await in its latest version, allowing developers to write asynchronous code just like modern JavaScript. Instead of using callbacks or complex promise chaining, we can now write code that reads as easily as synchronous code but actually runs asynchronously.

Usage still requires caution regarding error handling and exception propagation, as it’s not the same as regular try-catch. Developers need to understand that async/await in ClojureScript behaves slightly differently from JavaScript.

I think adding this feature helps ClojureScript reach more new developers, especially those already familiar with modern JavaScript patterns.

ClojureScript async/await Code Screenshots

Looking at the code examples, you can see that the new syntax is much more readable than using go blocks with <!. Instead of writing (go (let [result (<! (fetch-data))] ...)), we can now write (async (let [result (await (fetch-data))] ...)) directly.

Real-world usage still requires caution with error handling because await will throw exceptions when Promises reject. I think having this syntax makes ClojureScript code look more like JavaScript while maintaining its functional programming nature well.

When Promise Management Became a Nightmare

Previously, writing async code in ClojureScript was quite a headache because you had to mix JavaScript’s .then and catch with ClojureScript syntax. Code would become callback hell that was very hard to read, especially when chaining multiple Promises together.

(.then (fetch-user-data user-id)
  #(.then (fetch-user-posts (:id %))
    #(.then (process-posts %)
      #(update-ui %))))

Adding error handling made code even more complex, requiring .catch at every step. I think back then, writing async in ClojureScript lost much of functional programming’s elegance because code became imperative instead.

Position in the ClojureScript Ecosystem

async/await in ClojureScript is a significant step that will help this language compete better with JavaScript. Currently, ClojureScript relies on Promise chains or core.async channels, which are difficult for new developers to understand.

Compared to JavaScript async/await, which has been around for a long time, ClojureScript is about 7 years behind. But coming late means learning from various problems JavaScript has already encountered, especially regarding error handling and debugging.

I think adding async/await will help attract more JavaScript developers to try ClojureScript. Right now, the barrier to entry is quite high - people coming from JavaScript need to learn core.async entirely from scratch, which takes time and is quite complex.

Comparison: Old Way vs. New Way

Factor Promise ChainingAsync-Await
Syntax (.then (.catch chain))(await (async-fn))
Error Handling Separate in .catchtry/catch block
Nested Calls Multiple nested .thenWritten as sequence
Debugging Hard to traceLike sync code
Learning Curve Must understand core.asyncFamiliar for JS devs

The old promise chaining approach often makes code look complex, especially with multiple nested calls. Debugging is also difficult because stack traces jump around.

I think async/await is what will make JavaScript developers feel more comfortable, because the syntax is very similar to JavaScript ES2017. You can handle errors with regular try/catch without having to remember complex core.async patterns.

Real-world Scenarios Where async/await Helps

Multi-level API Calls

When you need to fetch user profile then use the ID to get posts, async/await is much more readable than promise chains. Just write let user = await getUser() then let posts = await getPosts(user.id) and you’re done.

Error Handling Management

try/catch works normally, no need to .catch() at every point. If any API fails, you can catch it in one place. Very convenient.

Parallel Requests

Works beautifully with Promise.all, like await Promise.all([getUsers(), getPosts()]) - wait for everything together but write it readably.

Working with DOM Events

Event handlers that need to call APIs when clicked can use async functions directly. I think writing onClick={async () => await saveData()} is more comfortable than setting up new promises.

Comparison with Other Alternatives

Factor ClojureScriptJavaScriptDart
Syntax (js-await promise)await promiseawait future
Error Handling try-catch + macrostry-catch nativetry-catch native
Performance Compile-time optimizeRuntime overheadAOT compiled
Learning Curve Must learn LispAlready familiarEasier than JS

ClojureScript async/await provides the same benefits as JavaScript but wrapped in macro form. The (js-await) syntax might look strange, but you get immutability and functional programming along with it.

JavaScript async/await remains the easiest standard to use because everyone already knows it. I think if the team has no Lisp experience, JavaScript is still better because of the lower learning curve.

Dart async/await compiles to machine code so it’s faster, but it’s only used in the Flutter ecosystem.

Pros and Cons

Pros

  • +syntax close to JavaScript makes it easy for devs coming from JS to learn
  • +interoperates with almost all JavaScript libraries
  • +functional programming + async/await provides better state management than alternatives
  • +compiles to performant JavaScript

Cons

  • much smaller community than JavaScript, hard to find team members
  • longer build times than TypeScript
  • complex debugging because you need to look at compiled JS
  • high learning curve for those who haven't written Lisp

I think ClojureScript async/await is suitable for projects that truly need functional programming. If the team consists of regular JavaScript developers, TypeScript is still better because of its larger ecosystem and easier hiring.

For work requiring heavy immutable state management, like financial apps or real-time data processing, ClojureScript would be a good choice.

Hidden Costs

Browser support isn’t much of an issue because ClojureScript compiles to regular ES5 JavaScript. But build size is the real headache - minimum bundle is around 200KB+ even if we only write a few lines of code.

There is some performance overhead at runtime because of managing immutable data structures and persistent collections. But in most production apps, you won’t notice much difference.

Learning curve is most important. If the team has never written functional programming before, it will take at least 2-3 months to adjust. I think you need to carefully consider whether it’s worth the time investment, because finding additional people is difficult and maintenance might be problematic in the future.

Who Should and Shouldn’t Use It

Should use: Teams with functional programming background, or building complex interactive web apps like data visualization, real-time dashboards. Suitable for projects requiring immutability and managing very complex state.

Shouldn’t use: New teams unfamiliar with functional programming, projects needing quick delivery, or startups having trouble finding people. Regular content websites don’t need it because React/Vue already work fine.

Worthwhile use cases: Financial applications needing clear audit trails, game engines with complex state management, or tools for data analysis.

I think if the team has experience and the project has flexible timelines, it’s worth trying. But if you’re rushing to deliver, React is still safer.

Summary and Recommendations

ClojureScript’s async/await is a significant step that makes writing asynchronous code much more readable, but it’s not yet the main reason to migrate from existing JavaScript frameworks.

Recommended for: Developers with functional programming experience, teams requiring strict immutability, or long-term projects where performance is crucial. Enterprise apps handling complex business logic will benefit greatly.

Not recommended if: Most of the team are JavaScript beginners, you have tight deadlines, or need a broad ecosystem for third-party libraries.

I think if an organization is looking at long-term investment and ready to invest in the learning curve, start with a side project first. You’ll immediately know whether it fits your workflow or not.