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

无法在控制器内部访问来自工厂的angularjs数据,angularjs,Angularjs,我编写了一个从本地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.execu

我编写了一个从本地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 ;});
此工厂用于控制器中获取数据。代码为:

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

我使用console.log检查数据是否实际进入工厂。我在控制台中从工厂得到结果,但不是从控制器得到的。请告诉我哪里出了问题。我使用LocalData作为临时变量来存储数组“data”中的数据。

这似乎是工厂异步获取数据的问题。在您的控制器中,您正在获取数据,然后立即将其记录下来,但在db.transaction调用完成之前,数据只是一个空列表

即,工厂将立即返回起始listData(即[]),然后在db调用完成后对其进行修改。您的控制器不等待此操作

您需要在控制器中使用$scope.$watch-in用户(除非您将工厂重新编写为使用承诺),以查看它何时更新。如果您只是想在模板中使用它,那么这可能不是必需的。默认情况下,模板可以很好地处理承诺,但是如果您想在javascript中使用它,则需要观察或让工厂使用承诺

因此,用手表:

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

保留现在没有测试它:)

实际上,如果异步检索该值,最好返回一个
承诺,而不是监听值更改

此外,工厂应该始终返回一个对象,该对象包含可以在注入后调用的方法,而不是单个函数的结果。这不是
工厂的工作方式

我会像这样重写您的代码:

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
    }
  }

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

  readData.transaction()
    .success(function (data) {
      console.log(data)
    })
})
然后,您可以将其注入某个控制器并检索结果,如下所示:

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
    }
  }

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

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

编辑:更新代码以解决错误的
返回。承诺

我尝试了你的代码,但我遇到了一个错误“无法读取未定义的属性'success'”你能纠正它吗,因为我是angularjs的新手,这个概念对我来说是非常新的东西。你说得对,我错放了延迟的
返回。promise
。无论如何,为了你自己的利益,你应该学会调试和解决这类小问题,否则你永远也学不到JavaScriptHere是promises的文档,阅读起来很好(按照角度文档标准,这很容易,不是说很多)。多莫坤就在这里,一个承诺比我建议的手表要好(而且是一件重要的事情)