Angular没有从承诺的FS.readFile中获取数据

我正在尝试使用Angular服务来调用fs.readFilefs.writeFile这取决于按下的button的types,以便了解节点和angular度许诺如何交互。 我所拥有的是读写文件,但是不会发回读取的数据,也不会为了解错误而抛出任何错误。

 //HTML <button ng-click="rw('write')">WRITE FILE</button> <button ng-click="rw('read')">READ FILE</button> //angular angular.module('test', []) .controller('ctrl', function($scope, RWService){ $scope.rw = function(type){ RWService.rw(type) .then( function(res){ console.log('success'); }, function(err){ console.log('error'); }) }; }) .service('RWService',['$http', '$q', function($http, $q){ this.rw = function(type){ var promise = $http.get('./rw/' + type); var dfd = $q.defer(); promise.then( function(successResponse){ dfd.resolve(successResponse); }, function(errorResponse){ dfd.reject(errorResponse); } ); return dfd.promise; }; }]); //node var fs = require('fs') , async = require('async') , Q = require('Q'); var dest = './file.txt'; var rw = { write: function(data){ data = data.repeat(5); return Q.nfcall(fs.writeFile, dest, data); } , read: function(data){ data = data.repeat(5); var deferred = Q.defer(); console.log('inside read'); fs.readFile(dest, 'utf8', function(err, data){ if (err){ deferred.reject('some error'); }else{ deferred.resolve(data); } }); return deferred.promise; } }; module.exports = exports = rw; //node server app.get('/rw/:type', function(req, res, next){ var type = req.params.type; var data = 'some text string\n'; if (type == 'write'){ //omitted fro brevity }else{ rw.read(data) .then(function(response){ return {'response': response}; }) .catch(function(err){ return {'index.js error': err}; }); } }); 

我从这个博客文章中构build了angular度$q部分。

这里是你的代码的原生Promise实现。

 var fs = require('fs'); var dest = './file.txt'; var rw = { write: function(data){ return new Promise(function (resolve, reject) { data = data.repeat(5); fs.writeFile(function (err, result) { if (err) return reject(err.message); return resolve(result); }); }); }, read: function(data){ return new Promise(function (resolve, reject) { data = data.repeat(5); fs.readFile(dest, 'utf8', function(err, contents) { if (err) return reject(err.message); return resolve(contents.toString()); }); }); } }; module.exports = exports = rw; 

[编辑:我只是改变了代码,把data=data.repeat(5)的承诺工厂方法。 基本上,如果有什么事情可以引发exception,你应该尝试把它放在承诺函数中,否则你又会冒着再次沉默的脚本来杀死脚本。]

几个意见:

返回deferred是非常有用的,但你必须小心你如何使用它。 如果asynchronous代码不能包装在一个简单的函数中(比如在其构造函数中创build承诺并在不同子方法中parsing/拒绝的类实例),我个人只会使用它。 就你而言,可能发生的情况是,脚本以fs.readFile()永远不会被调用的方式失败,所以deferred.resolve()deferred.reject()将永远不会被调用。 在这种情况下,你需要使用try / catch,并且总是在那里调用deferred.reject() 。 这是很多额外的工作,很容易避免。

相反,你应该尝试使用Promise的香草标准实现,如上所见。

最后, Q是一个开创性的图书馆,基本上教会了全世界如何做承诺,但是它并没有经过多年的更新,从来没有特别的丰富和快速。 如果你需要更多的function,可以看看when.js *,kew或Bluebird(注意Bluebird声称是最快的,但是我个人认为这是不真实的)。

(*我真的很喜欢用when.js工作,使用愚蠢的本地承诺发现它有点痛苦,但是,嘿标准就是标准。


[编辑:添加事物angular度的细节]

所以根据你的评论,这是我怀疑你也在寻找。 你会看到在这里我使用$http.get()作为唯一的承诺。 一旦你在一个promise中,不需要使用defer() ,所以实际上不需要包含$q

对不起,我从来没有使用过service() 。 即使Angular创build服务的自己的文档使用factory()方法,所以这就是我在这里使用的。

 .factory('RWService',['$http', function($http){ return { rw: function (type) { // $http returns a promise. No need to create a new one. return $http.get('./rw/' + type) .then(function (response) { // You can do other stuff here. Here, I am returning the // contents of the response. You could do other stuff as // well. But you could also just omit this `then()` and // it would be the same as returning just the response. return response.data; }) .catch(function (err) { // You can do other stuff here to handle the error. // Here I am rethrowing the error, which is exactly the // same as not having a catch() statement at all. throw err; }); } }; }]); 

如果你阅读上面的代码中的注释,你应该认识到你可以写这样的代码:

 .factory('RWService',['$http', function($http){ return { rw: function (type) { return $http.get('./rw/' + type); } }; }); 

唯一的区别是RWService.rw()将最终parsing整个响应对象而不是响应数据。

这里要记住的是,你可以(也绝对应该)尽可能地回收你的承诺。 基本上,所有你需要知道的承诺是:

  1. 每一个承诺都有一个then方法,你可以把你的逻辑包装进去;
  2. then每一次都catch回去作为一个新的承诺;
  3. 如果你在任何时候抛出一个exception或catch ,你将被直接扔到下一个catch ,如果有一个;
  4. 如果你从任何一个返回一个值或catch它,它将作为parameter passing给链中的下一个;
  5. 当链条用完时,或者你抛出一个exception,并没有更多的catch ,承诺链结束; 和
  6. then catch速度很快,但是它们仍然是asynchronous的,所以如果你不真正需要它们,就不要将新的元素添加到承诺链中。