JavaScript asynchronous programming and javascript asynchronous programming

Source: Internet
Author: User
Tags emit

JavaScript asynchronous programming and javascript asynchronous programming

With the development of the front-end, the word Asynchronous is becoming more and more common. Suppose we have such an asynchronous task:

Initiate several requests to the server. The result of each request is used as the parameter of the next request.
Let's take a look at our solutions:

Callbacks

The first and most commonly used callback function is the callback function. Let's perform simple encapsulation:

let makeAjaxCall = (url, cb) => {  // do some ajax  // callback with result}makeAjaxCall('http://url1', (result) => {  result = JSON.parse(result)})

Well, it looks good! But when we try to nest multiple tasks, the code looks like this:

makeAjaxCall('http://url1', (result) => {  result = JSON.parse(result)  makeAjaxCall(`http://url2?q=${result.query}`, (result) => {    result = JSON.parse(result)    makeAjaxCall(`http://url3?q=${result.query}`, (result) => {      // ...    })  })})

Oh, my God! Let the heap go.}) Hell!

So we want to tryJavaScript event model:

1. Pub/Sub

In DOM event processing, Pub/Sub is a common mechanism. For example, we need to add event listening to elements:

elem.addEventListener(type, (evt) => {  // handler})

So can we also construct a similar model to process asynchronous tasks?

First, build a distribution center and add the on/emit method:

let PubSub = {  events: {},  on(type, handler) {    let events = this.events    events[type] = events[type] || []    events[type].push(handler)  },  emit(type, ...datas) {    let events = this.events    if (!events[type]) {      return    }    events[type].forEach((handler) => handler(...datas))  }}

Then we can use it like this:

const urls = [  'http://url1',  'http://url2',  'http://url3']let makeAjaxCall = (url) => {  // do some ajax  PubSub.emit('ajaxEnd', result)}let subscribe = (urls) => {  let index = 0  PubSub.on('ajaxEnd', (result) => {    result = JSON.parse(result)    if (urls[++index]) {      makeAjaxCall(`${urls[index]}?q=${result.query}`)    }  })  makeAjaxCall(urls[0])}

There seems to be no revolutionary change to the callback function, but the advantage is that we can put the request and processing functions in different modules to reduce coupling.

2. Promise

The Promise specification is a revolutionary change. With Promise, we can complete asynchronous tasks like this:

let makeAjaxCall = (url) => {  return new Promise((resolve, reject) => {    // do some ajax    resolve(result)  })}makeAjaxCall('http://url1')  .then(JSON.parse)  .then((result) => makeAjaxCall(`http://url2?q=${result.query}`))  .then(JSON.parse)  .then((result) => makeAjaxCall(`http://url3?q=${result.query}`))

Great! It is written like a synchronous function!

Don't worry, boy. We also have better:

3. Generators

Another major killer of ES6 is Generators [2]. In a generator function, we can use yield statements to interrupt function execution and use the next method to iterate statements outside the function, more importantly, we can use the next method to inject data into the function and dynamically change the behavior of the function. For example:

function* gen() {  let a = yield 1  let b = yield a * 2  return b}let it = gen()it.next() // output: {value: 1, done: false}it.next(10) // a = 10, output: {value: 20, done: false}it.next(100) // b = 100, output: {value: 100, done: true}

Use generator to encapsulate our previous makeAjaxCall functions:

let makeAjaxCall = (url) => {  // do some ajax  iterator.next(result)}function* requests() {  let result = yield makeAjaxCall('http://url1')  result = JSON.parse(result)  result = yield makeAjaxCall(`http://url2?q=${result.query}`)  result = JSON.parse(result)  result = yield makeAjaxCall(`http://url3?q=${result.query}`)}let iterator = requests()iterator.next() // get everything start

Oh! It looks like the logic is clear, but it feels uncomfortable to inject iterator from the outside every time ......

Don't worry. Let's mix Promise and Generator to see what black magic will be produced:

let makeAjaxCall = (url) => {  return new Promise((resolve, reject) => {    // do some ajax    resolve(result)  })}let runGen = (gen) => {   let it = gen()  let continuer = (value, err) => {    let ret    try {      ret = err ? it.throw(err) : it.next(value)    } catch (e) {      return Promise.reject(e)    }    if (ret.done) {      return ret.value    }    return Promise      .resolve(ret.value)      .then(continuer)      .catch((e) => continuer(null, e))  }  return continuer()}function* requests() {  let result = yield makeAjaxCall('http://url1')  result = JSON.parse(result)  result = yield makeAjaxCall(`http://url2?q=${result.query}`)  result = JSON.parse(result)  result = yield makeAjaxCall(`http://url3?q=${result.query}`)}runGen(requests)

The runGen function looks like an automatic machine!

In fact, the runGen method is an implementation of ECMAScript 7 async function:

4. async function

ES7 introduces a more natural feature async function [3]. With the async function, we can complete the task as follows:

let makeAjaxCall = (url) => {  return new Promise((resolve, reject) => {    // do some ajax    resolve(result)  })};(async () => {  let result = await makeAjaxCall('http://url1')  result = JSON.parse(result)  result = await makeAjaxCall(`http://url2?q=${result.query}`)  result = JSON.parse(result)  result = await makeAjaxCall(`http://url3?q=${result.query}`)})()

Just like when we combine Promise and Generator in the above section, the await keyword also accepts a Promise. In async function, the remaining statements are executed only after the await statement is completed. The whole process is like encapsulating Generator with runGen function.

The above are some JavaScript asynchronous programming modes summarized in this article. I hope this will be helpful for your learning.

Articles you may be interested in:
  • Javascript asynchronous programming
  • Four Asynchronous Javascript programming methods allow you to write better programs
  • Six features of the Promise mode in JavaScript asynchronous programming
  • Detailed introduction to the Javascript asynchronous programming model Promise Mode
  • Detailed introduction to asynchronous programming specification Promises/A in Javascript
  • Nodejs asynchronous programming
  • How to use javascript to solve asynchronous programming exceptions
  • Understanding javascript asynchronous programming

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.