javaScript回调进化史(含源码)

对于编程时的I/O操作,从最开始用的setTimeout()到jQuery的Deferred,以及近两年经常用到的Promise、Generator、async,深深感觉到技术一直在进步,能解决的问题越来越多,使用越来越方便,今天正好有时间就把这些东西大致整理下。可以去下载源码测试,直接node app1.js就可以看到结果,对于最后一个例子需要node v7.2.0以上

本文的源码放在了  https://github.com/binginsist/binginsistNote/tree/master/javaScript回调进化史 


I/O操作的问题

我们都知道当遇到I/O操作时,会出现代码不按顺序执行的问题,比如下面这个例子,虽然“console.log("虽然我在最后,但是我第一个输出,不信你瞧")”这句话在最后的位置,可是这句话是先输出的,并且另外三个操作也不是按顺序输出的。这给我们的编程带来很大的麻烦,我们无法使用前面操作的结果。一个方法就是使用setTimeout(),setTimeout()可参考这个链接http://www.css88.com/archives/5804,当然另一个方法就是使用回调,也是本文主要讲的内容。

//1.I/O操作案例(用读取文件的方式模拟)
var fs = require("fs");

fs.readFile("./data/1.txt",function(err,data){
	console.log(data.toString());
});

fs.readFile("./data/2.txt",function(err,data){
	console.log(data.toString());
});

fs.readFile("./data/3.txt",function(err,data){
	console.log(data.toString());
});

console.log("虽然我在最后,但是我第一个输出,不信你瞧")

//输出结果: 虽然我在最后,但是我第一个输出,不信你瞧,2.txt,1.txt,3.txt(不按顺序输出所以结果不一定)

	


回调地狱案例

这个例子中,我们有三个读取文件的操作需要按顺序输出,可以使用这种方式。现在才3层嵌套,我都看不下去了,如果有要读取10个文件怎么办,这就进入了所谓的回调地狱。

//2.回调地狱案例
var fs = require("fs");

fs.readFile("./data/1.txt",function(err,data){
	console.log(data.toString());
		//第二层
		fs.readFile("./data/2.txt",function(err,data){
				console.log(data.toString());
					//第三层
					fs.readFile("./data/3.txt",function(err,data){
						console.log(data.toString());
					});
			});
});			
//输出结果: 1.txt,2.txt,3.txt(按顺序输出)

	

Promise进化

2015 年 6 月ES6正式发布,其提供的  Promise 对象着实让我们方便了一把,从此我们走上了将异步操作以同步操作的流程表达出来的光明大道。喜欢jQuery的Deferred得朋友可能会感到非常熟悉,是的他们很像!

//3.Promise案例
var fs = require("fs");

function readText(text) {
	//用Promise包装读取文件的方法,return回Promise对象
    return new Promise(function(resolve, reject) {
        fs.readFile("./data/"+text,function(err,data){
        	dataTwo=data.toString();
        	//将本次函数执行后的结果dataTwo通过resolve抛出
			resolve(dataTwo);
		});
    });
}

//调用readText函数
readText("1.txt").then(function(data){
	//data接收resolve抛出的结果
	console.log("第1次读取文件的结果"+data);
	//执行一些操作后,调用第二个函数并return回
	return readText("2.txt");
}).then(function(data){
	//data接收到第二个函数resolve抛出的结果
	console.log("第2次读取文件的结果"+data);
	//执行一些操作后,调用第三个函数并return回
	return readText("3.txt");
}).then(function(data){
	//data接收到第三个函数resolve抛出的结果
	console.log("第3次读取文件的结果"+data);
	//再执行其他方法
})


//输出结果:
// 第1次读取文件的结果1.txt
// 第2次读取文件的结果2.txt
// 第3次读取文件的结果3.txt

	

Promise.all

当然只有Promise是不够的,只是变成同步并不能让我们满意,比如我们一个页面有很多请求,等数据都加载好了再去取消loading页面;或者需要把所有的文件读取完再进行某种操作。能不能让那些操作并发进行,最后再一次性执行其他操作,事实告诉我们这是可以的,因为有了Promise.all,请看下面案例。

//4.Promise.all案例
var fs = require("fs");

function readText(text) {
	//用Promise包装读取文件的方法,并返回Promise对象
    return new Promise(function(resolve, reject) {
        fs.readFile("./data/"+text,function(err,data){
        	dataTwo=data.toString();
        	//将本次函数执行后的结果dataTwo通过resolve抛出
			resolve(dataTwo);
		});
    });
}

let arr = [];
//并发处理读取文件的操作
arr.push(readText("1.txt"));
arr.push(readText("2.txt"));
arr.push(readText("3.txt"));

Promise.all(arr).then(function (datas) {
    // 最终处理,datas 是所有返回结果的数组
    console.log("返回数据为", datas);
});

//输出结果:[ '1.txt', '2.txt', '3.txt' ]


	

Generator

Generator 的基础这里就不细说了,可以参考http://es6.ruanyifeng.com/#docs/generator这篇文章,这里要注意的是Generator 函数需要有启动器运行它,就是下例中的run函数。

//5.Generator案例
var fs = require("fs");

function readText(text) {
    return new Promise(function(resolve, reject) {
        fs.readFile("./data/"+text,function(err,data){
        	dataTwo=data.toString();
			resolve(dataTwo);
		});
    });
}

//5.Generator函数
function* gen() {
  let text1 = yield readText("1.txt");
  let text2 = yield readText("2.txt");
  let text3 = yield readText("3.txt");
  console.log(text1, text2, text3);
}

//Generator函数启动器
function run(gen) {
  var g = gen();

  function next(d) {
    var r = g.next(d);
    r.done || r.value.then(function(d){ next(d) }); // 这个是关键,把值传回传
  }

  next();
}

//运行启动器
run(gen);

//输出结果: 1.txt 2.txt 3.txt


	

async

作为Generator的语法糖,async更加简化了我们的代码,让我也爱上了这种方式,并且一个词生动形象的表现出这个函数的作用,没错它就是await。但是要注意的是node 的低版本不支持这些特性,建议node v7.2.0以上。

//6.async案例(注意使用node v7.2.0以上)
var fs = require("fs");

function readText(text) {
    return new Promise(function(resolve, reject) {
        fs.readFile("./data/"+text,function(err,data){
        	dataTwo=data.toString();
			    resolve(dataTwo);
		  });
    });
}


async function run() {
  let text1 = await readText("1.txt");
  let text2 = await readText("2.txt");
  let text3 = await readText("3.txt");
  console.log(text1, text2, text3);
}

run();

//输出结果: 1.txt 2.txt 3.txt


	


Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值