JS Asynchronous request

Source: Internet
Author: User

The current async / await feature has not been added to the ES2016 standard, but does not mean that these features will not be added to JavaScript in the future. When I wrote this article, it had reached the third draft and was developing rapidly. These features have been supported by IE edge, and it will reach the fourth edition, when the feature will be logged in to other browsers-paving the road for joining the next version of the language (see also: TC39 process).

We've heard about features for some time now, so let's go into it and see how it works. In order to be able to understand the content of this article, you need to have a deep understanding of promise and generator objects. These resources may be able to help you.

    • ES6 350-point overview
    • Deep ES6 Promise
    • Deep ES6 Generator
    • Implementing asynchronous I/O using generator and promise
    • Visualization Tools for Promise

using Promise

Let's assume that we have code like the following. Here I wrap an HTTP request in an Promise object. This promise returns the object when it succeeds body , and causes it to be returned when rejected err . It pulls HTML content for a random article in this blog (the original author's blog) Every time.

require(‘request‘);function getRandomPonyFooArticle () {  return new Promise((resolve, reject) => { request(‘https://ponyfoo.com/articles/random‘, (err, res, body) => { if (err) { reject(err); return; } resolve(body); }); });}

The typical usage of the above promise code is as written below. There, we created a new promise chain to convert a subset of DOM objects in an HTML page into a markdown, then convert it to terminal-friendly output, and then use the console.log output. Always remember to add the processor for your promise .catch .

var hget =require ( ' Hget ');  var marked = require ( ' marked '); require ( ' marked-terminal ');p rintrandomarticle (); Span class= "hljs-function" >function printrandomarticle  () {getrandomponyfooarticle (). Then (HTML = hget (HTML, {markdown:  At-subscribe,.mm-comments,. De-sidebar '}). Then (MD = marked (MD, {renderer: new term ()})). Then (txt = Console.lo g (TXT)). catch (reason = console.error (reason));}        

When the code runs, this code will produce output like the following.

The code above is "better than a callback function," which makes you feel like you're reading the code sequentially.

using the Generator (generator)

In the past, through exploration, we found that generators can be obtained by means of a "synchronous" synthesis html . Even if the code now has some synchronous notation, which involves quite a bit of packaging, and the generator may not be the most straightforward way to achieve the results we expect, we may eventually insist on using promise instead.

functionGetrandomponyfooarticle(Gen) {var g = gen (); Request ( ' Https://ponyfoo.com/articles/random ', (Err, res, body) = {if (err) {G.throw (err); return; } g.next (body); });} Getrandomponyfooarticle (function* printrandomarticle  () {var html = Span class= "Hljs-keyword" >yield; var MD = hget (HTML, {markdown: true, Root:  ' main ', ignore:  At-subscribe,.mm-comments,.de-sidebar '}); var txt = marked (MD, {renderer: new term ()}); Console.log (TXT);}) ;

“请记住,在使用promise时,你应该将yield调用包装在try/catch块中来保留我们添加的错误处理器”

Not that you know, using generators like this is not easy to extend. In addition to the intuitive syntax involved, your iteration code is highly coupled to the generator function, which reduces extensibility. This means that you need to modify it frequently when you add a new await expression to the builder. A better alternative is to use the upcoming async function .

using async/await

When the Async function finally hits the ground, we will be able to take the promise-based implementation and use it with the advantage that it writes asynchronously like a write synchronization generator. Another benefit of this approach is that you do not need to modify the getRandomPonyFooArticle method at all, and it waits until it returns a promise.

It is important to note that an await can only be async used with a keyword in a function to work in a similar way to the generator, until the promise is finished and the processing is paused in your context. If the wait expression is not a promise, it will also be transformed into a promise.

read();async function read () { var html = await getRandomPonyFooArticle(); var md = hget(html, { markdown: true, root: ‘main‘, ignore: ‘.at-subscribe,.mm-comments,.de-sidebar‘ }); var txt = marked(md, { renderer: new Term() }); console.log(txt);}

“再次, -- 跟生成器一样 -- 记住,你最好把`await`包装到`try/catch`中,这样你就可以在异步函数中对返回后的promise进行错误捕获和处理。”

In addition, an async function always returns an Promise object. This promise is rejected when an uncaught exception occurs, otherwise it will handle async the return value of the function. This allows us to invoke a async function and mix with regular promise-based extensions. The following example shows a combination of two methods (see Babel's interactive interpreter).

 async function asyncfun (var value = await Promise. Resolve (1). Then (x = = x * 3). Then (x = x + 5). Then (x = x/2); return value;} Asyncfun () then (x = console.log ( ' x: ${x} ')); //<-' x:4 '            

Back in the previous example, that means we can extend it from the 异步读取 function and 返回文本 allow the caller to use promise or another async function . That way, your 读取 function will simply focus on pulling the terminal-readable markdown from a random article on pony foo.

async function read () { var html = await getRandomPonyFooArticle(); var md = hget(html, { markdown: true, root: ‘main‘, ignore: ‘.at-subscribe,.mm-comments,.de-sidebar‘ }); var txt = marked(md, { renderer: new Term() }); return txt;}

You can then call it further in another async function await read() .

async function write () { var txt = await read(); console.log(txt);}

Or you can just use the Promise object for further expansion.

read().then(txt => console.log(txt));

Fork

In an asynchronous code flow, it is always possible to run two or more tasks at the same time. When async functions are easier to write asynchronous code, they also pass themselves to code in turn. This means that the code performs only one operation at a time . A function that contains more than one await expression is paused at each expression until the Promise object finishes executing and before moving to the next await expression await --just as we observed at the generator and yield keyword.

You can use it Promise.all to resolve the ability to create a single Promise object and wait. The biggest problem, of course, is getting used to making everything run serially Promise.all , or that will bring performance bottlenecks to your code.

The following example shows how you can work with three different promise objects at the same time 等待 . A particular await operator pauses your Async function, along with the 等待 Promise.all expression, and ends up being parsed into an 结果 array, and we can use the destructor to pull a single result in the array one at a time.

async function concurrent () { var [r1, r2, r3] = await Promise.all([p1, p2, p3]);}

In some cases, you can await * change the code snippet above so that you don't have to use Promise.all to wrap your promise object. Babel 5 still supports this feature, but it has been removed from the specification (also removed from Babel 6)-For these reasons

async function concurrent () { var [r1, r2, r3] = await* [p1, p2, p3];}

You can still do something with similar all = Promise.all.bind(Promise) code to get a neat alternative Promise.all . On top of that, you can do the Promise.race same thing, and that's not equivalent to using it await* .

const all = Promise.all.bind(Promise);async function concurrent () { var [r1, r2, r3] = `await all([p1, p2, p3])`;}

Error Handling

It is important to note that in asynchronous functions, errors are swallowed "silently" -just like in a normal promise object. Unless we await add blocks around the expression- try/catch -regardless of whether 暂停 they occur in your 异步 function body or when it pauses--the Promise object is rejected and an error is returned through the Async function.

Naturally, this can be seen as a capability: You can use try/catch blocks of code, something you can't do with a callback function--but you can do it with a promise object. In this case, theasync function is similar 生成器 , thanks to the function execution Pause feature, you can make use try/catch of the asynchronous stream code as the synchronous code look like.

In addition, you can Async catch these exceptions outside of the function by simply adding a method call to the Promise object that they return .catch() . Trying to .catch combine error handling in a Promise object try/catch is a more flexible approach, but it can also cause confusion and eventually cause errors to be unhandled.

read()  .then(txt => console.log(txt))  .catch(reason => console.error(reason));

We need to be cautious and alert ourselves to different ways of finding errors, handling errors, or preventing errors.

How to use async/await it today

Today, there is a way to use the async function in your code by Babel. This involves a series of modules, but as long as you want, you can always come up with a module to wrap all this code in. I'm included npm-run as a useful way to keep everything locally installed with the package.

npm i -g npm-runnpm i -D   browserify   babelify   babel-preset-es2015   babel-preset-stage-3   babel-runtime   babel-plugin-transform-runtimeecho ‘{  "presets": ["es2015", "stage-3"], "plugins": ["transform-runtime"]}‘ > .babelrc

When using babelify support for an async function , the following commands will be example.js browserify compiled. You can then use the pipeline to transfer the script to node execution, or save the script to the hard disk.

npm-run browserify -t babelify example.js | node

Deep Reading

The async function specification is surprisingly short and should be an interesting reading if you are keen to learn more about these upcoming features.

I have pasted a piece of code below, it is to help you understand async how the function inside is working. Even if we can't fill in the new keywords, it can also help you understand async/await what's going on behind the curtain.

“换句话说,它应该对学习异步函数内部原理非常有帮助,无论是对生成器还是promise。”

First, the following small piece of code shows how to async函数 simplify the declaration process by using a regular function keyword, which returns the result of a build generator spawn function--which we think await is syntactically and yield equivalently.

 async function example  (A, B, c) {example function body} function example  (A, B, c) {return Spawn (function*  () {Example Span class= "hljs-function" >function body}, this);}    

In spawn , promise is wrapped in code and passed into the generator function, executed serially through user code, and passes the value into your "generator" code (the function async body of the function). In this sense, we can note that the async function is really a syntactic sugar on top of the generator and the Primose object, which is important for you to understand how each of these links works, so that you have a mix, match, There is a better understanding of how to combine different asynchronous code streams.

functionSpawn(Genf, self) {ReturnNew Promise (function (resolve, reject) {var gen = Genf.call ( self); Step (() = Gen.next (undefined)); function step  (NEXTF) {var next; try {next = NEXTF ();} catch (e) {//failed and rejected Promise object Reject (e); return; } if (next.done) {//executed successfully, processing Promise object Resolve (Next.value); Span class= "Hljs-keyword" >return; } //not completed, the Promise object with the yield tag is interrupted, and the Step method Promise.resolve (next.value) is executed here. Then (v = step (() = Gen.next (v)), E = Step (() = Gen.throw (e)); } });} 

JS Asynchronous request

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.