【问题标题】:Angular js two way data binding works only with applyAngular js 两种方式数据绑定仅适用于应用
【发布时间】:2016-10-19 15:46:29
【问题描述】:

我的 Angular 应用程序具有/需要两种方式的数据绑定。

我使用注入到控制器中的角度服务从 indexedDB 中获取数据。

从 db 获取数据后,我需要更新视图。

var app = angular.module("app",["ngRoute"]);

app.config(['$routeProvider',function($routeProvider) {
    //removed extra routes for simplicity
    $routeProvider.when('/grouped',{
        templateUrl: 'template/grouped.html',
        }).otherwise({
        redirectTo: '/grouped'
    });
}]);

同一文件中的控制器

 app.controller("AppController",function ($scope,dexiedb) {
    $scope.datais={};
    $scope.dataisdata={};
    $scope.alldata = {};

    var scholar = {};

    var _db;
    window.initial = 0;
    var callback_alldata = function(err,data){
      if(!err){
      /* If I put apply it works*/
      // $scope.$apply(function() {
        $scope.alldata = data;
            // });
      }
    console.log('in callback_alldata ',err,data);
    };

    var init = function() {
      console.log('hi in init');
      dexiedb.getdata(callback_alldata);
      console.log($scope);
    };
  init(); 
 });

从 db 获取数据的服务

app.service('dexiedb',function(){

  var createdData = {};
  var _db = null;

  var service = {};
  //Initialization code which makes connection
  service.init = function(){

  _db = new Dexie('puppets');
  _db.version(1).stores({
        snips: "++id, text",
        parent: "++id, title, timeStamp"
    });

   _db.open().then(function(){
      service.createdata();
      console.log('service.init then called');
     }).catch(function(e){
      console.log('error opening',e);
            });
  };
  //The actual place where data is fetched and returned
   service.createdata = function(callback){
      console.log('createdata');
        var alldata = [];
      _db.transaction('rw',_db.parent, _db.snips, function(){

        _db.parent.each(function(par){
          var r = {'parent':par,'snips':[]};
          _db.snips.where('URL').equals(par.URL).each(function(snip){
              r.snips.push(snip);
          });
          alldata.push(r);
          // console.log(alldata);
        }).then(function(){
          createdData = alldata;
          console.log('createdata',createdData);
          return callback(null,createdData);
          // return createdData;
        });
      });
    };
//The method which is called in the controller
service.getdata = function(callback){
  // console.log(createdData);
  if (Object.keys(createdData).length==0) {
    console.log('createdData was empty');
    return service.createdata(callback);
  } else return callback(null,createdData);
}

service.init();

return service;

 });

我知道如果要更新变量的位置不在角度范围内,则应使用$scope.apply。在回调中不会出现角度范围吗?

数据已获取并登录到控制台,但在我单击另一条路线然后再次返回之前,它不会显示在视图中。

我对 promises/callback 的理解还不是很清楚,问题是由于回调处理不当造成的吗?

【问题讨论】:

  • 为什么不使用原生的 $http 模块来发出请求?
  • 数据库在浏览器本身。我不需要 http 请求
  • 啊,我明白了。好吧,你知道你想使用 Promise 是正确的——因为你仍在执行异步操作。看看使用 Angular $q library for promises。

标签: javascript angularjs asynchronous 2-way-object-databinding dexie


【解决方案1】:

问题在于 Angular 不知道对 $scope 所做的更改(即$scope.alldata = data;)。

对控制器中的$scope 所做的更改将立即更新,但是您的代码在回调中。 Angular 在触发回调之前到达控制器的末尾,因此它错过了摘要周期。它无法知道您的回调已被调用。

当您在回调中更新 $scope 时,不会触发新的摘要循环。

dexiedb 似乎没有使用$http,因此在这种情况下您需要使用$scope.$apply。你可以看到angular's implementation of $http,其中包括$apply

【讨论】:

  • 谢谢,这是有道理的。使用 apply 时可以完成这项工作。单击另一条路线Error: $digest already in progress 时,我也会收到错误消息。使用$timeout 解决它,你能解释一下这里发生了什么吗?
  • 如果您在控制器中直接调用 $scope.$apply 而不是回调,则会收到该错误,因为摘要已经在进行中。更具体地说,Angular 已经知道它需要触发其观察者,因此不需要过早地触发观察者,并且可能会引入许多不希望的副作用。但是,$timeout 会等待当前摘要完成,然后再调用新摘要。
猜你喜欢
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 2019-02-05
  • 1970-01-01
  • 1970-01-01
  • 2012-10-14
相关资源
最近更新 更多