异步javascript,callback、Promise?我们用Generator!
2016-08-16 22:13
344 查看
ES6提供了两个处理异步Js的特性:Promise和Generator。我们这里会介绍这两个新特性,并在最后讲解如何使用Generator。为了使本文更加贴近实际,我们使用一个网络请求库request来作为异步任务的实例使用。
他们都是顺序执行,方法执行完成之后打印结果。
但是在nodejs里,对于异步执行的js是行不通的,比如异步下载一个文件、HTTP访问一个接口等。除非获取
在ES6之前,代码是没办法停下来的。所以我们只有使用回调:
引入
使用
调用Promise化的方法。这时你可以调用then方法了。
ES6中可以使用Generator了。不严谨的说Generator主要由两部分组成。一个是
最后结果是多少?
使用第三方库可以使得Generator方法暂停、在运行。基本上是这样的:
注意:yield后面的语句必须是一个Promise,最后return的也是一个Promise。
在上文已经介绍过,这个是被
这是一个Generator方法,在执行的时候会在
上面的代码的并行执行例子:
如果在一个Generator方法里yield一个Generator方法数组的话,数组里的这些方法会并行执行。最后耗时远小于顺序执行的时间。
request库是一个强大而简单易用的网络请求库。她支持http和https,也支持redirect。以后在新的工作里也许就会用得着。
基本概念
如果你使用过其他的编程语言,那么一般调用方法的时候是这样的:let result = function(...); console.log(`${result}`);
他们都是顺序执行,方法执行完成之后打印结果。
但是在nodejs里,对于异步执行的js是行不通的,比如异步下载一个文件、HTTP访问一个接口等。除非获取
result的方法调用可以等待,一直到结果返回之后再调用
console.log(${result}
);
在ES6之前,代码是没办法停下来的。所以我们只有使用回调:
var request = require('request'); request('http://www.baidu.com', (err, res, body) => { if (err) { console.log(`ERROR:- ${err}`); return; } console.log(`Request done`); });
request执行完成的时候就会调用
(err, res, body) => {}的回调。
Promise是一个更好的处理回调的方法。更多内容可以看这里。
// 1 var Promise = require('bluebird'); var request = require('request'); // 2 Promise.promisifyAll(request); // 3 request.getAsync('http://www.baidu.com').then((data)=>{ console.log('request'); console.log(`${data.body}`); });
引入
bluebird库。
bluebird就是一个在ES5下实现Promise的库。
使用
bluebird库把
request库全部的方法都转化为返回Promise对象的方法。在调用这些方法的时候只需要在原方法名称后加Async的后缀。
调用Promise化的方法。这时你可以调用then方法了。
ES6中可以使用Generator了。不严谨的说Generator主要由两部分组成。一个是
function关键字后面的*号,一个是方法体中的
yield语句。如:
function* foo(x) { var y = 2 * (yield (x + 1)); var z = yield (y / 3); return (x + y + z); } var b = foo(5); b.next() // { value:6, done:false } b.next(12) // { value:8, done:false } b.next(13) // { value:42, done:true }
最后结果是多少?
使用第三方库可以使得Generator方法暂停、在运行。基本上是这样的:
var Promise = require('bluebird'); var request = require('request'); Promise.promisifyAll(request); var testFunc = Promise.coroutine(function *() { console.log('hello world'); // let result = yield Promise.resolve('hello yield world'); let result = yield request.getAsync('http://www.baidu.com'); console.log(`${result}`); return result; }); testFunc().then(value => { console.log(`### ${value}`); });
注意:yield后面的语句必须是一个Promise,最后return的也是一个Promise。
request.getAsync('http://www.baidu.com'); console.log(`${result}`); return result; });
在上文已经介绍过,这个是被
bluebird库Promise化之后的方法调用,返回的就是一个Promise。
代码
这里深入探讨一下Generator。那么,就请主角入场:function *echo(text, delay = 0) { const caller = yield; setTimeout(() => caller.success(text), delay); };
这是一个Generator方法,在执行的时候会在
const caller = yield;这一句暂停,等待获取caller对象。在下面的例子里
echo方法会被顺序的执行三次:
run(function* () { console.log(yield echo('this')); console.log(yield echo('is')); console.log(yield echo('a test')); }); //Output: //this //is //a test
上面的代码的并行执行例子:
run(function* parallelEchos() { let startTime = Date.now(); let texts = yield [ echo('this', 1000), echo('is', 900), echo('a test', 800) ]; console.log(`##Parallex:- ${texts}`); console.log(`##Time used:- ${Date.now() - startTime}`); }); //Output: //##Parallex:- this,is,a test //##Time used:- 1005
如果在一个Generator方法里yield一个Generator方法数组的话,数组里的这些方法会并行执行。最后耗时远小于顺序执行的时间。
最后
ES7的proposal里有一个async-await关键字的组合。解决了一个Generator非常的大的问题。Generator需要调用
next方法来不断的往下执行
yield语句,要自动执行就需要一个执行器,比如TJ的co。bluebird的
coroutine方法实现了这个功能。
相关文章推荐
- JavaScript及其异步实现续:Promise让一切更简单
- JavaScript异步回调的Promise模式封装实例
- 学习JavaScript中的异步Generator
- Callback Promise Generator Async-Await 和异常处理的演进
- ECMAScript 6 入门笔记(五)异步promise,Generator,async
- 使用Promise模式来简化JavaScript的异步回调
- javascript异步代码的回调地狱以及JQuery.deferred提供的promise解决方式
- 学习JavaScript中的异步Generator
- Callback Promise Generator Async-Await 和异常处理的演进_2
- 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
- Callback and Promise in Javascript
- Javascript异步流程控制之Promise(2)-Angular $q源码解读
- Javascript异步流程控制之Promise(1)-Angular $q简介
- ArcGIS API for JavaScript 4.2学习笔记[7] 鹰眼(缩略图的实现及异步处理、Promise、回调函数、监听的笔记)
- Callback Promise Generator Async-Await 和异常处理的演进
- JavaScript异步回调的Promise模式封装实例
- 用 ES6 generator & Promise 写异步代码
- [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑