起因
为了改进之前那个爬虫代码,决定狠下心来好好学习一下ES6新东西 — Promise, 以及第三方package Q, 来改善异步代码书写
遇到的问题
网上好多资源都是空谈理论,即使给出例子也不具体,要么是给一个大概框架,剩下留给你自己想象,要么是甩给你一个 XMLHttpRequest 请求实现,结果还是一脸懵逼
Pormise 作用大概总结
它允许你为异步代码执行结果的成功和失败分别绑定相应的处理方法(handlers )
—-来自MDN
样例!样例!样例!
Pormise api 使用
- Promise.prototype.then
- Promise.prototype.catch
- 以上两者返回自身,所以可以进行链式调用
/**
* 新建一个函数,返回一个Promise
* 输入参数:data,不能大于20,否则抛出错误
* 作用:为输入的数加一(用时1s,用于模拟实际的http请求或读写文件出现的延时)
*/
let p1 = function (data) {
/**
* 返回一个新的Promise对象,千万要记得返回啊啊啊啊啊!
* 参数 resolve : 执行成功
* 参数 reject : 执行失败(这里的情况是data大于20)
*/
return new Promise((resolve, reject) => {
if (data > 20) {
// 失败
reject(new Error('More than twenty'));
}
// 使用setTimeout来模拟1s延迟
setTimeout(() => {
// 成功
resolve(++data);
}, 1000);
});
};
// 传入参数2进行测试
p1(2)
// 如果p1执行成功,则输出执行结果,并返回执行结果供链式调用的下一个then调用
.then((data) => {
console.log('第一个then', data);
return data;
})
.then((data) => {
// 重新使用这个函数
console.log('第二个then,第二次调用函数p1');
return p1(data);
})
.then( (data) => {
console.log('第三个then',data);
})
// 如果上面then链任何一处执行失败(data>20),这抛出的错误会在这里接收,并进行处理
.catch((err) => {
console.error(err);
});
- 运行测试
- 那么要是出现错误来呢?将最初的参数改为20
- 当然,还有一些东西,这里就不多介绍来了,我觉得目前足够用了,可以看看官方文档
Q的使用
实话说,它的官方文档看的我一脸蒙蔽,然后到处找教程,最后在youtube上找到一个讲的不错的,贴一个链接,还没翻墙的可以下一个lantern就行啦
API:Q.defer() 使用
这里使用这个api改写上面的内容
// 需要 npm install q
const Q = require('q');
let p1 = function (data) {
// 这里去掉了new Promise
let deferred = Q.defer();
if (data > 20) {
// 使用reject方法,和原生的reject效果一样
deferred.reject(new Error('More than twenty'));
return deferred.promise;
}
setTimeout(() => {
// 使用resolve方法,和原生的resolve效果一样
// 如果·出错,立刻返回promise,和之前的 return new Promise(... 效果一样
deferred.resolve(++data);
}, 1000);
// 返回promise,和之前的 return new Promise(... 效果一样
return deferred.promise;
};
// 用法相同,把最初的测试数据改为10
p1(10)
.then((data) => {
console.log('第一个then', data);
return data;
})
.then((data) => {
console.log('第二个then,第二次调用函数p1');
return p1(data);
})
.then( (data) => {
console.log('第三个then',data);
})
.catch((err) => {
console.error(err);
});
运行结果
当然,如果把最初的参数改为20,会怎么样呢?
API:Q.denodify 使用
nodejs的标准模块都是事先封装好的,那个如果还想使用上述的then已经catch该怎么办呢,是用Q.denodify 就行啦
这里还是用之前的函数来演示
// 这里p1为传统的异步函数,也就是参数中存在回调函数
let p1 = function (data, callback) {
if (data > 20) {
let err = new Error('More than twenty');
return callback(err);
}
setTimeout( () => {
data += 1;
callback(null, data);
}, 1000);
};
// 使用 Q.denodeify, 将 p1 变为Pormise函数
p1 = Q.denodeify(p1);
// 使用方法相同,将测试数据改为15
p1(15)
.then((data) => {
console.log('第一个then', data);
return data;
})
.then((data) => {
console.log('第二个then,第二次调用函数p1');
return p1(data);
})
.then( (data) => {
console.log('第三个then',data);
})
.catch((err) => {
console.error(err);
});
运行结果
出现错误的情况和前面一样,这里就不再贴图了 :-p
总结
总算是搞懂了,还差实战,而且Q还有许多高大上的方法,后面再慢慢发掘吧,目前觉得够用了 :-)