More than React
More than React (1) Why ReactJS is not suitable for complex front-end projects?
More than React (2) React.Com Ponent Compromises reusability?
More than React (3) The Virtual DOM is Dead?
More than React (4) HTML can be statically compiled?
More than React (5) Is Asynchronous programming really Good?
In this paper, starting from InfoQ:http://www.infoq.com/cn/articles/more-than-react-part05
The last article in the More Than React series can also be compiled by HTML? You’ve seen how Binding.scala statically checks for syntax and semantic errors while rendering HTML to avoid bugs and write more robust code. This article discusses how Binding. Scala and other front-end frameworks send requests to the server and display them on the page.
In past front-end development, requesting data from the server required asynchronous programming techniques. The concept of asynchronous programming is simple: when an I/O operation is performed, the current execution stream is not blocked, but the result of the I/O is processed through a callback function. Unfortunately, this concept is simple but cumbersome to use, and can lead to a lot of bugs if misused, as well as complex and harder to maintain programs that handle asynchronous events with care.
Binding. Scala replaces asynchronous programming with Binding of I/O state, making applications simpler, more readable, and more business-friendly.
I’ll use a DEMO page that loads avatars from Github as an example of why asynchronous programming can lead to complex code and how binding. scala can solve this problem.
DEMO Function Requirements
As a DEMO user, you will see a text box when you open the page.
Enter any Github user name in the text box and the profile picture corresponding to the user name will be displayed at the bottom of the text box.
To do this, you can use the Github API to send an HTTPS request for user information.
The acceptance criteria for the complete process of sending a request and rendering an avatar are as follows:
- If the user name is empty, please enter a user name is displayed.
- If the username is not empty, initiate the Github API and display different content based on the API result:
* If the load is not complete, a message "Loading" is displayed;Copy the code
</pre>
'* If successfully loaded, parse the response into JSON, extract the avatar URL and display it; `Copy the code
* Display error message if loading error.Copy the code
Asynchronous programming and MVVM
In the past, we used asynchronous programming in front-end development to send requests and get data. Examples include ECMAScript 2015 Promise and HTML 5 fetch API. To render this data on a web page, we used to use the MVVM framework. Keep modifying the View Model as you fetch the data, and then write the View to render the View Model on the page. This way, dynamic information about the loading process can be reflected on the page. For example, ReactJS state is the View Model, and Render is the View, which renders the View Model to the page. The implementation with ReactJS and Promise is as follows:
`class Page extends React.Component { state = { githubUserName: null, isLoading: false, error: null, avatarUrl: null, }; currentPromise = null; sendRequest(githubUserName) { const currentPromise = fetch(`https://api.github.com/users/${githubUserName}`); this.currentPromise = currentPromise; currentPromise.then(response => { if (this.currentPromise ! = currentPromise) { return; } if (response.status > = 200 & & response.status < 300) { return response.json(); } else { this.currentPromise = null; this.setState({ isLoading: false, error: response.statusText }); } }).then(json => { if (this.currentPromise ! = currentPromise) { return; } this.currentPromise = null; this.setState({ isLoading: false, avatarUrl: json.avatar_url, error: null }); }).catch(error => { if (this.currentPromise ! = currentPromise) { return; } this.currentPromise = null; this.setState({ isLoading: false, error: error, avatarUrl: null }); }); this.setState({ githubUserName: githubUserName, isLoading: true, error: null, avatarUrl: null }); } changeHandler = event => { const githubUserName = event.currentTarget.value; if (githubUserName) { this.sendRequest(githubUserName); } else { this.setState({ githubUserName: githubUserName, isLoading: false, error: null, avatarUrl: null }); }}; render() { return ( < div> < input type="text" onChange={this.changeHandler}/> < hr/> < div> { (() => { if (this.state.githubUserName) { if (this.state.isLoading) { return < div> {`Loading the avatar for ${this.state.githubUserName}`}< /div> } else { const error = this.state.error; if (error) { return < div> {error.toString()}< /div>; } else { return < img src={this.state.avatarUrl}/>; } } } else { return < div> Please input your Github user name< /div>; } })() } < /div> < /div> ) ; }} '</pre> all 100 lines of code. Because the whole process was made up of several closures, the code to set and access the state was scattered, so debugging was cumbersome, and it took me two nights to tune through 100 lines of code. Now we have binding. scala. Since binding. scala supports automatic remote data Binding, we can write: <pre>`@dom def render = { val githubUserName = Var("") def inputHandler = { event: Event => githubUserName := event.currentTarget.asInstanceOf[Input].value } < div> < input type="text" oninput={ inputHandler }/> < hr/> { val name = githubUserName.bind if (name == "") { < div> Please input your Github user name< /div> } else { val githubResult = FutureBinding(Ajax.get(s"https://api.github.com/users/${name}")) githubResult.bind match { case None => < div> Loading the avatar for { name }< /div> case Some(Success(response)) => val json = JSON.parse(response.responseText) < img src={ json.avatar_url.toString }/> case Some(Failure(exception)) => < div> { exception.toString }< /div> } } } < /div> } '</pre> total 25 lines of code. Complete the DEMO please visit [ScalaFiddle] (https://scalafiddle.io/sf/JGxViqE/1). And the reason why it's so simple, Because Binding. Scala works [FutureBinding] (HTTP: / / https://javadoc.io/page/com.thoughtworks.binding/unidoc_2.11/latest/com/thoughtworks/binding/FutureBindi Ng.html) uses the API request as a normal binding expression to represent the current state of the API request. Each 'FutureBinding' state has three possibilities, 'None' indicating that the operation is in progress, 'Some(Success(...)) ) 'indicates success,' Some(Failure(...) ) 'indicates that the operation fails. Remember the '.bind 'of the binding expression? It means "each time it changes". Because 'FutureBinding' is also [Binding] (https://javadoc.io/page/com.thoughtworks.binding/unidoc_2.11/latest/com/thoughtworks/binding/Binding.html) So we can use '.bind 'to express the semantics whenever the state of the remote data changes. As a result, with Binding.scala, every line of code we write can correspond to a single sentence in the acceptance criteria that describes business specifications rather than technical details like "asynchronous processes." Let's review the acceptance criteria to see how they correspond to the source code:Copy the code
- If the user name is empty, please enter a user name is displayed.
if (name == "") { & amp; lt; div& amp; gt; Please input your Github user name& amp; lt; /div& amp; gt;Copy the code
- If the username is not empty, initiate the Github API and display different content based on the API result:
} else { val githubResult = FutureBinding(Ajax.get(s"https://api.github.com/users/${name}")) githubResult.bind match {Copy the code
* If the load is not complete, a message "Loading" is displayed; & lt; pre& gt;Copy the code
case None =>< /pre> & lt; div& gt; Loading the avatar for { name }& lt; /div& gt;Copy the code
* Parses the response into JSON, extracts the avatar URL and displays it if it loads successfully; < pre>Copy the code
case Some(Success(response)) =& gt;
val json = JSON.parse(response.responseText) < img src={ json.avatar_url.toString }/> `
* Display error message if loading error. <pre>`case Some(Failure(exception)) =& gt; // If there is a loading error,Copy the code
< div> { exception.toString }< /div> // Error information is displayed.
-
`}}
conclusion
This article contrasts the asynchronous programming of ECMAScript 2015 with the FutureBinding of Scala. Binding. Scala is less conceptual, more powerful, and more business-friendly.
Technology stack | ReactJS + Promise + fetch | Binding.scala |
---|---|---|
Programming paradigm | MVVM + Asynchronous programming | Remote data binding |
How do I manage the data loading process | Programmers write asynchronous programming code by hand | Automatic processing |
Ability to directly describe acceptance criteria in code | Can’t | can |
Load the data from the RESTful API and display the required lines of code | Line 100 | 25 lines |
These five articles cover some of the challenges of a front-end project that implements complex interactions with ReactJS and how Binding. Scala solves them, including:
- reusability
- Performance and Accuracy
- HTML template
- Asynchronous programming
In addition to the above four aspects, ReactJS state management is also a big problem. If a third party library such as Redux or React-Router is introduced to handle state, it will lead to complex architecture, more layers and more code twists and turns. Binding.scala can describe complex state using the same data Binding mechanism as page rendering, providing server communication, state management, and url distribution without the need for any third-party libraries.
If you’re working on complex front-end projects and are having a hard time using ReactJS or another development framework, you can solve those problems with Binding.scala. The Binding.scala Quick Start guide covers every step of creating a binding. scala project from scratch.
Afterword.
Everybody’s Got to Learn How to Code — Obama
Programming languages are the languages in which people talk to computers. For those who master programming languages, computers are an extension of their brains and a part of their bodies. So, a person who can’t program is like an angel without wings.
A computer program is an amazing thing. It can work, see, hear, talk, just like life. Those who can program are creating life, doing God’s work.
I have a dream that programming can be mastered by everyone as basic skills as speaking and writing.
If web designers know binding. scala, they don’t need engineers to implement their designs, they can just add magic symbols to their prototypes. Bind, and create moving web pages.
If QA, BA, or product managers know binding.Scala, they write acceptance criteria and no longer need to check if the programmer did the right thing, they can automatically turn acceptance criteria into working features.
I tried to eliminate unnecessary technical details from the design of Binding.scala so that when a person uses binding. scala, he only needs to focus on what he wants to convey to the computer.
Binding. Scala is a small step towards my dream. I hope it becomes not just a tool for front-end engineers, but also a stepping stone for everyone else into programming.
A link to the
- Binding.scala project home page
- Binding. Scala • TodoMVC project home page
- Binding.scala • TodoMVC DEMO
- Binding. Scala • Other DEMO other than TodoMVC
- Guide to porting JavaScript to Scala.js
- Scala.js project home page
- Scala API Reference documentation
- Scala. Js API reference documentation
- Scala. Js DOM API reference documentation
- Binding. Scala quick start Guide
- Binding.scala API reference documentation
- Binding. Scala’s Gitter chat room
For more insights, please follow our wechat official account: Sitvolk