简体   繁体   English

无法在控制器内部访问工厂的angularjs数据

[英]angularjs-data from factory cannot be accessed inside the controller

I have written a factory for getting data from local websql database.The code is as below: 我已经写了一个工厂从本地websql数据库中获取数据。代码如下:

app.factory('readData', function () {
var localData=[];
var data=[];
var db = openDatabase("here is ma database");
var selectAllStatement = "SELECT * FROM tablename"; 

  db.transaction(function (tx) {
        tx.executeSql(selectAllStatement, [], function (tx, result) {
             dataset = result.rows;
            for (var i = dataset.length - 1; i >= 0; i--) {
             data[i]=dataset.item(i);

            }; 
              localData=data;

            console.log(data);  
            return localData; 

        });

    });
return localData ;});

This factory is used in a controller to get the data.The code is: 该工厂用于控制器中以获取数据。代码为:

function tricoreContrller($scope, readData) {$scope.users = readData;console.log( $scope.users);}tricoreContrller($scope, readData);

I have used console.log to check whether the data is actually coming in factory.I get result in console from factory but not from controller.Plz tel me where i am going wrong.I have used LocalData as temperary variable to store the data from array "data". 我使用console.log来检查数据是否真的在工厂中。我从工厂而不是从控制器中获得控制台中的结果。请告诉我我哪里出问题了。我已使用LocalData作为临时变量来存储来自数组“数据”。

This looks to be a problem with the factory getting it's data asynchronously. 这似乎是工厂异步获取数据的问题。 In your controller you are getting the data and then logging it straight away, but until the db.transaction call is complete the data is just an empty list. 在您的控制器中,您正在获取数据,然后立即将其记录下来,但是在db.transaction调用完成之前,数据只是一个空列表。

Ie the factory will return the starting listData (which is []) straight away, and then it will modify it once the db-call is done. 即工厂将立即返回起始listData(为[]),然后在完成数据库调用后将对其进行修改。 Your controller does not wait for this. 您的控制器无需等待。

You will want to use a $scope.$watch in user in your controller (unless you re-write the factory to use promises), to see when it updates. 您将要在控制器中的用户中使用$ scope。$ watch(除非您重写工厂以使用promises),以查看其更新时间。 This might not be necessary if you just want to use it in a template, templates handle promises pretty well by default, but if you want to use it in the javascript you need to watch or have the factory use a promise. 如果您只想在模板中使用它,则默认情况下模板处理promise的效果可能不是必须的,但是如果要在javascript中使用它,则需要监视或让工厂使用promise。

So with a watch: 所以用手表:

$scope.$watch('user', function(newVal, oldVal) {
    if (newVal !== oldVal) {
        console.log('Value changed!', newVal)
    } 
}

With reservations for not having tested it right now :) 保留不立即测试的资格:)

Actually, if the value gets retrieved asynchronously, you should better return a promise , instead of listening to a value change. 实际上,如果异步获取值,则最好返回一个promise ,而不是监听值的更改。

Also, factories should always return an object with methods that you can invoke after injecting it, not the result of a single function. 同样,工厂应始终返回带有在注入对象后可以调用的方法的对象,而不是单个函数的结果。 This is not how factory are supposed to work. 这不是factory应该如何工作的。

I would rewrite your code like this: 我会这样重写您的代码:

app.factory('readData', function ($q) {

  var localData=[];
  var data=[];
  var db = openDatabase("here is ma database");
  var selectAllStatement = "SELECT * FROM tablename";

  // here starts your public API, that is the method you can invoke
  return {
    transaction: function () {

      // initialize a deferred method
      var deferred = $q.defer()

      db.transaction(function (tx) {
        tx.executeSql(selectAllStatement, [], function (tx, result) {
          // you forgot about 'var' here
          var dataset = result.rows;

          for (var i = dataset.length - 1; i >= 0; i--) {
            data[i]=dataset.item(i);
          }

          // set your data as the successful result of your promise
          deferred.resolve(data)

        })
      })

      // return the promise (that is, the async data)
      return deferred.promise
    }
  }

})

And then you can inject it in some controller and retrieve the result like this: 然后,您可以将其注入到某些控制器中,并像这样检索结果:

app.controller('myCtrl', function (readData) {

  readData.transaction()
    .success(function (data) {
      console.log(data)
    })
})

Edit: updated code to address misplaced return.promise 编辑:更新了代码以解决错位的return.promise

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM