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

Angular not getting data from FS.readFile with promises

本文关键字:承诺 获取 数据 readFile FS Angular      更新时间:2023-09-26

我正在尝试使用Angular服务来调用使用fs.readFilefs.writeFile,具体取决于按下的按钮类型,以了解节点和角度承诺如何交互。我所拥有的是读取写入文件,但不发回读取数据,也不会抛出任何错误让我了解出了什么问题。

//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};
    });
  }
});

我构建了这篇博文的角度$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)放入承诺工厂方法中。基本上,如果有什么东西可以引发异常,你应该尝试把它放在那个 promise 函数中,否则你再次冒着再次默默杀死脚本的风险。

几点评论:

返回deferred非常有用,但您必须小心使用它的方式。我个人仅在异步代码无法包装在简单函数中时才使用它(例如在其构造函数中创建承诺并在不同的子方法中解析/拒绝的类实例(。在您的情况下,可能正在发生的事情是脚本以一种fs.readFile()永远不会被调用的方式失败 - 因此永远不会达到deferred.resolve()deferred.reject()。在这种情况下,您需要使用 try/catch 并始终在其中调用deferred.reject()。这是很容易避免的大量额外工作。

相反,您应该尝试使用上面看到的 Promise 的原版标准实现。

最后,Q是一个开创性的图书馆,基本上首先教会了世界如何做承诺,但它已经多年没有更新了,而且从来没有特别丰富或快速。如果您需要更多功能,请查看 when.js*、kew 或 Bluebird(请注意,Bluebird 声称是最快的,但我个人发现这是不真实的。

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


[编辑:在事物的角度方面添加细节]

因此,根据您的评论,我怀疑您也在寻找以下内容。你会看到,我在这里用$http.get()作为唯一的应许。一旦你进入一个承诺,就不需要使用defer(),所以实际上甚至不需要包含$q

对不起,我从来没有用过service().甚至 Angular 自己关于创建服务的文档也使用 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(( 最终将解析整个响应对象而不是响应数据。

这里要记住的是,你可以(而且绝对应该(尽可能多地回收你的承诺。基本上,您需要了解的有关承诺的只是:

  1. 每个承诺都有一个thencatch的方法,你可以把你的逻辑包裹起来;
  2. 每一个thencatch都作为新的承诺回归;
  3. 如果你在任何thencatch中抛出异常,你会被直接抛到下一个catch,如果有的话;
  4. 如果你从任何thencatch返回一个值,它将作为参数传递给链中的下一个then;
  5. 当链用完then,或者你抛出异常并且没有更多的catch ES,承诺链结束;
  6. thencatch都很快,但它们仍然是异步的,所以如果你真的不需要它们,就不要向承诺链添加新元素。