当前位置:首页 > 技术分析 > 正文内容

nodejs Q 使用

ruisui883周前 (04-07)技术分析16

## 背景 ##

### 同步api与异步api ##

nodejs中有同步api和异步api;通常情况下建议使用异步api,以提高程序的执行效率.

同步api优缺点:

- (优点)易于使用,逻辑清晰

- (缺点)使用耗时较长(如io操作)的api,程序的执行效率会非常低

异步api优缺点:

- (优点)使用耗时较长(如io操作)的api,也不会降低程序的执行效率

- (缺点)不易使用,逻辑容易乱

### 异步的问题 ###

关键在于异步api的结果如何传递

例如 读取文件:

fs.readFile(file, options, callback);//(err, data)

fs.readFileSync(file, options);//data, throw Error

同步api通过函数"返回值"返回结果

异步api通过"回调函数"返回结果

回调函数存在的问题:回调嵌套

例如 顺序读取3个文件:

fs.readFile(file1, function (){

fs.readFile(file2, function () {

fs.readFile(file3, function () {

//回调嵌套层数多了会使程序变得复杂

});

});

});

### 解决嵌套问题 ###

解决办法就是换一种思路:回归同步api的结果返回方式,使用"返回值"将结果带回

很明显,异步的结果不会直接在"返回值"中取到,只能间接取到

Promise,这是一个概念模型,Promise对象可以携带异步api的计算结果,可以访问Promise对象得到结果(当然得到结果也会是一个异步的)

## 是什么 ##

q是Promise的一个实现,定义了若干方便易用的api.

## 有什么用 ##

解决异步嵌套的问题

除了Promise,还有其他一些为了解决异步api使用的方案,包括 async, eventproxy

缺点也比较明显,async的嵌套问题没有解决,eventproxy使用的方式更容易使逻辑变得复杂

异步api得到简化,看上去更接近同步的api

嵌套层数明显减少

## 怎么用 ##

### 生成一个Promise对象 ###

//方式1

var readFile = function (file, options) {

var defer = Q.defer();

fs.readFile(file, options, function (err, data) {

if (err) {

defer.reject(err);

} else {

defer.resolve(data);

}

});

return defer.primise;

};

//方式2

var readFile = function (file, options) {

return Q.Promise(function (resolve, reject) {

fs.readFile(file, options, function (err, data) {

if (err) {

reject(err);

} else {

resolve(data);

}

});

});

};

//方式3

Q.resolve(data);

Q.reject(err);

### 访问Promise的值 ####

var promise1 = readFile('/path/to/the/data', {});

var promise2 = promise1.then(function (data) {

//data 就是文件'/path/to/the/data'的内容

});

通过Promise对象的then方法就可以访问Promise对象的值,同时会生成一个新的Promise对象

//then的定义

promise.then(onFulfilled, onRejected, onProgress)

### Promise的值 ###

Promise的对象的值有两种:fulfilled和rejected

Promise的对象的值一旦确定就不再改变,且可以被反复访问

var promise1 = readFile('/path/to/the/data', {});

var promise2 = promise1.then(function (data) {

//data 就是文件'/path/to/the/data'的内容

});

var promise3 = promise1.then(function (data) {

//data 还是文件'/path/to/the/data'的内容,

//而且'/path/to/the/data'实际只被读了1次

});

### 通过then或catch得到的新的Promise对象的值 ###

promise.then(function () {

//return data;

//return Q.resolve(data);

//return Q.reject(new Error('error message'));

//throw new Error('error message');

});

### Promise对象链式调用 ###

//假设函数f1,f2,f3,f4都是异步的且都返回Promise对象,

//并且要求f1,f2,f3,f4顺序被执行

//形式1:

var promise1 = f1();

var promise2 = promise1.then(function () {

return f2();

});

var promise3 = promise2.then(function () {

return f3();

});

var promise4 = promise3.then(function () {

return f4();

});

promise4.then(function () {

//f1,f2,f3,f4顺序被执行完成

});

//形式2:

f1().then(function () {

return f2().then(function () {

return f3().then(function () {

return f4().then(function () {

//f1,f2,f3,f4顺序被执行完成

});

});

});

});

//形式3:

f1().then(function () {

return f2();

}).then(function () {

return f3();

}).then(function () {

return f4();

}).then(function () {

//f1,f2,f3,f4顺序被执行完成

});

### Q.all(promisesArray) ###

同时进行多个异步操作

Q.all([

fs.readFile(file1, {}),

fs.readFile(file2, {})

]).then(function (results) {//[file1Data, file2Data]

//当异步调用都成功的时候才执行这里

}, function () {

//当存在失败的异步调用时执行这里

});

QQ群:323934521

www.niefengjun.cn

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/3333.html

标签: readfilesync
分享给朋友:

“nodejs Q 使用” 的相关文章

GitLab-合并请求

描述合并请求可用于在您对项目进行的其他人员之间交换代码,并轻松与他们讨论更改。合并请求的步骤步骤1-在创建新的合并请求之前,GitLab中应该有一个创建的分支。您可以参考本章来创建分支-步骤2-登录到您的GitLab帐户,然后转到“ 项目”部分下的项目 -步骤3-单击“ 合并请求”选项卡,然后单击“...

抖音 Android 性能优化系列:启动优化实践

启动性能是 APP 使用体验的门面,启动过程耗时较长很可能使用户削减使用 APP 的兴趣,抖音通过对启动性能做劣化实验也验证了其对于业务指标有显著影响。抖音有数亿的日活,启动耗时几百毫秒的增长就可能带来成千上万用户的留存缩减,因此,启动性能的优化成为了抖音 Android 基础技术团队在体验优化方向...

虚幻引擎5.5现已发布 手游开发、动画制作重大改进

Epic在今天发布了虚幻引擎5.5,现可通过Epic Launcher下载。此版本在动画创作、渲染、虚拟制片、移动端游戏开发和开发人员迭代工具集等方面做出了重大改进。 官方博客:虚幻引擎5.5现已发布,在动画创作、虚拟制作和移动游戏开发方面取得了显著进步,渲染、摄像机内视觉特效和开发人员迭代等领域的...

Vue进阶(幺叁捌):vue路由传参的几种基本方式

1、动态路由(页面刷新数据不丢失)methods:{ insurance(id) { //直接调用$router.push 实现携带参数的跳转 this.$router.push({ path: `/particulars/${id}`,...

vue打开新窗口并且实现传参,有图有真相

我要实现的功能是打开一个新窗口用来展示新页面,而且需要传参数,并且参数不能显示在地址栏里面,而且当我刷新页面的时候,传过来的参数不能丢失,要一直存在,除非我手动关闭这个新窗口,即浏览器的标签页。通过面向百度编程,发现网上的根本达不到这个效果,而且还都是坑,明明实现不了,还若有其事的写出来,于是我在标...

Vue Router 4 路由操作 - 路由导航

路由导航分为 声明式导航 和 编程式导航。通过 <router-link to="..."> 标签跳转的方式为声明式导航。通过 路由实例对象(router.push(...))跳转的为编程式导航。导航到不同的位置想要导航到不同的URL,使用 router.push 方法。...