code

Angularjs는 1.2에서 템플릿에 바인딩되지 않습니다.

starcafe 2023. 3. 14. 21:46
반응형

Angularjs는 1.2에서 템플릿에 바인딩되지 않습니다.

1.2로 업그레이드한 후 서비스로부터 반환된 약속이 다르게 동작합니다.간단한 서비스 myDates:

getDates: function () {
           var deferred = $q.defer();

            $http.get(aGoodURL).
                 success(function (data, status, headers, config) {
                     deferred.resolve(data);  // we get to here fine.
            })......

이전 버전에서는 컨트롤러에서 다음 작업을 수행할 수 있었습니다.

$scope.theDates = myDates.getDates();

getDates에서 반환된 약속은 Select 요소에 직접 바인딩될 수 있습니다.이것으로 동작하지 않고 컨트롤러의 약속에 따라 콜백을 제공해야 합니다.그렇지 않으면 데이터가 바인딩되지 않습니다.

$scope.theDates = matchDates.getDates();
$scope.theDates.then(function (data) {
      $scope.theDates = data;  // this wasn't necessary in the past

아직 의사 말이 있어요.

$q 약속은 템플릿엔진에 의해 angular로 인식됩니다.즉, 템플릿에서는 스코프에 부가된 약속을 결과값으로 간주할 수 있습니다.

이전 버전의 Angular에서는 동작하고 있었습니다만, 1.2 RC3의 자동 바인딩은 모든 심플한 서비스에서 실패합니다.내가 뭘 잘못하고 있는지 생각해 봐

1.2.0-rc3에는 다음과 같은 변경이 있습니다.

AngularJS 1.2.0-rc3 farwish-twitch는 $compile 및 $animate에서 우선순위가 높은 많은 문제를 수정하고 1.2를 위한 길을 열어줍니다.또한 이 릴리스에서는 일부 중요한 변경사항이 도입되어 경우에 따라서는 지시문과 템플릿이 파손될 수 있습니다.변경 사항을 이해하고 필요한 경우 코드를 마이그레이션하는 방법을 알아보려면 changelog를 읽어보십시오.이 릴리스의 자세한 내용은 changelog를 참조하십시오.

변경 로그에 설명이 있습니다.

$140:

  • 5dc35b52로 인해 $dc35b52와 템플릿은 더 이상 자동으로 약속을 해제하지 않습니다.이 기능은 더 이상 사용되지 않습니다.필요한 경우, 이행 기간 중에 를 통해 재활성화할 수 있습니다.$parseProvider.unwrapPromises(true)apiapi..
  • b6a37d11로 인해 rc.2에서 추가된 반환값이 약속일 경우(약속해제가 활성화되어 있는 경우 - 이전 포인트 참조) 반환값이 함수의 반환값을 해제하는 기능이 일반적인 사용 패턴을 깨서 반환되었습니다.

@Nenad에서 알 수 있듯이 약속은 더 이상 자동으로 참조되지 않습니다.이것은 지금까지 본 것 중 가장 기이한 결정 중 하나입니다.그것은, 내가 의지하고 있던 기능을 묵묵히 배제하기 때문입니다(그리고 그것은, 나에게 있어서, 각도의 특유한 판매 포인트 중 하나이며, 적은 것이 더 중요합니다).그래서 이걸 알아내는 데 시간이 꽤 걸렸어요.특히 $resource 프레임워크는 여전히 잘 작동하는 것 같기 때문입니다.게다가 이 또한 출시 후보입니다.만약 그들이 정말로 이것을 비난해야 한다면(그 주장들은 매우 미약하게 들림) 그들은 최소한 묵묵히 그것을 중단하기 전에 경고가 있었던 유예기간을 줄 수 있었을 것이다.보통은 각이 진 것에 매우 깊은 인상을 주지만, 이것은 큰 마이너스입니다.나는 이것이 실제로 되돌아간다고 해도 놀라지 않을 것이다, 비록 지금까지는 비교적 불평이 적은 것 같지만.

어쨌든 해결책은 뭐죠?

  • 항상 then()을 사용하고 $scope를 then 메서드로 할당합니다.

    function Ctrl($scope) {
       foo().then( function(d) { $scope.d = d; });
    )
    
  • 언랩 함수를 통해 값을 호출합니다.이 함수는 약속의 필드를 반환하고 이 필드를 then 메서드로 설정합니다.그러므로 그 약속이 해결되지 않는 한 그것은 정의되지 않을 것이다.

    $rootScope.unwrap = function (v) {
      if (v && v.then) {
        var p = v;
        if (!('$$v' in v)) {
          p.$$v = undefined;
          p.then(function(val) { p.$$v = val; });
        }
        v = v.$$v;
      }
      return v;
    };
    

    다음과 같이 할 수 있습니다.

    Hello {{ unwrap(world) }}.
    

    이것은 http://plnkr.co/edit/Fn7z3g?p=preview 에서 온 것으로, 관련지어져 있는 이름은 없습니다.

  • 세트$parseProvider.unwrapPromises(true)메시지와 함께 살 수 있는 삶을 살 수 있습니다$parseProvider.logPromiseWarnings(false)다만, 다음의 릴리스에서는 기능이 삭제되는 경우가 있습니다.

하아, 40년 동안 스몰톡이 가진 건become오브젝트 참조를 전환할 수 있는 메시지입니다.그럴 수도 있었던 약속들...

갱신:

어플리케이션을 변경한 결과, 일반적인 패턴은 꽤 잘 동작하고 있는 것을 알 수 있었습니다.

오브젝트 'x'가 필요하고 이 오브젝트를 리모트로 취득할 수 있는 방법이 있다고 가정합니다.그러면 먼저 캐시에서 'x'를 확인합니다.물건이 있으면 돌려드립니다.이러한 객체가 존재하지 않으면 실제 빈 객체를 만듭니다.유감스럽게도 이 경우 어레이인지 해시/개체인지 확인해야 합니다.이 오브젝트는 다음 콜에서 사용할 수 있도록 캐시에 저장합니다.그런 다음 리모트콜을 시작하고 콜백 시 리모트시스템에서 얻은 데이터를 작성한 오브젝트에 복사합니다.캐시에 의해 get 메서드에 대한 반복 호출이 같은 오브젝트에 대해 많은 리모트콜을 생성하지 않게 됩니다.

 function getX() {
   var x = cache.get('x');
   if ( x == undefined) {
      cache.put('x', x={});
      remote.getX().then( function(d) { angular.copy(d,x); } );
   }
   return x;
 }

또 다른 방법은 get 메서드에 오브젝트의 수신처를 지정하는 것입니다.

 function getX(scope,name) {
   remote.getX().then( function(d) { 
       scope[name] = d;
   } );
 }       

언제든지 Common Angular 서비스를 만들고 오래된 약속의 작동 방식을 재현하는 언랩 방식을 넣을 수 있습니다.다음은 방법의 예를 제시하겠습니다.

var shared = angular.module("shared");

shared.service("Common", [
    function () {

        // [Unwrap] will return a value to the scope which is automatially updated. For example,
        //      you can pass the second argument an ng-resource call or promise, and when the result comes back
        //      it will update the first argument. You can also pass a function that returns an ng-resource or
        //      promise and it will extend the first argument to contain a new "load()" method which can make the
        //      call again. The first argument should either be an object (like {}) or an array (like []) based on
        //      the expected return value of the promise.
        // Usage: $scope.reminders = Common.unwrap([], Reminders.query().$promise);
        // Usage: $scope.reminders = Common.unwrap([], Reminders.query());
        // Usage: $scope.reminders = Common.unwrap([], function() { return Reminders.query(); });
        // Usage: $scope.reminders.load();
        this.unwrap = function(result, func) {
            if (!result || !func) return result;

            var then = function(promise) {
                //see if they sent a resource
                if ('$promise' in promise) {
                    promise.$promise.then(update);
                }
                //see if they sent a promise directly
                else if ('then' in promise) {
                    promise.then(update);
                }
            };

            var update = function(data) {
                if ($.isArray(result)) {
                    //clear result list
                    result.length = 0;
                    //populate result list with data
                    $.each(data, function(i, item) {
                        result.push(item);
                    });
                } else {
                    //clear result object
                    for (var prop in result) {
                        if (prop !== 'load') delete result[prop];
                    }
                    //deep populate result object from data
                    $.extend(true, result, data);
                }
            };

            //see if they sent a function that returns a promise, or a promise itself
            if ($.isFunction(func)) {
                // create load event for reuse
                result.load = function() {
                    then(func());
                };
                result.load();
            } else {
                then(func);
            }

            return result;
        };
    }
]);

이것은 기본적으로 오래된 약속대로 작동하며 자동으로 해결됩니다.단, 두 번째 인수가 함수일 경우 값을 스코프에 새로고침할 수 있는 ".load()" 메서드를 추가하는 이점이 있습니다.

angular.module('site').controller("homeController", function(Common) {
    $scope.reminders = Common.unwrap([], Reminders.query().$promise);
    $scope.reminders = Common.unwrap([], Reminders.query());
    $scope.reminders = Common.unwrap([], function() { return Reminders.query(); });
    function refresh() {
        $scope.reminders.load();
    }
});

이것들은 좋은 답변이었습니다.각도로 업그레이드 했을 때, 약속의 자동 포장이 기능하지 않게 되었을 때, 문제를 찾는 데 도움이 되었습니다.

Peter Kriens와 중복되는 위험을 무릅쓰고, 나는 이 패턴이 나에게 효과가 있다는 것을 알게 되었다(이것은 단순히 유명한 사람들의 인용구를 한 페이지에 넣는 단순한 예다).

마이 컨트롤러:

angular.module('myModuleName').controller('welcomeController',
function ($scope, myDataServiceUsingResourceOrHttp) {

    myDataServiceUsingResourceOrHttp.getQuotes(3).then(function (quotes) { $scope.quotes = quotes; });
}
);

마이 페이지:

...
<div class="main-content" ng-controller="welcomeController">
...
<div class="widget-main">
    <div class="row" ng-repeat="quote in quotes">
        <div class="col-xs-12">
            <blockquote class="pull-right">
                <p>{{quote.text}}</p>
                <small>{{quote.source}}</small>
            </blockquote>
                </div>
    </div>
</div>
...

언급URL : https://stackoverflow.com/questions/19472017/angularjs-promise-not-binding-to-template-in-1-2

반응형