如何在处理非 angular 代码时立即更新 $scope?

How to update $scope immediately when dealing with non angular code?

我必须处理非 angular 库并且需要在它们之间创建通信。

<div id="MoipWidget" data-token="{{personaltoken}}" callback-method-success="successCB" callback-method-error="errorCB"></div>

每次加载页面时,我都必须从服务器获取令牌。

$http.post('https://example.org', obj)
        .success(function(data){
            $scope.personaltoken = data.token;
            //Here I call the non angular library and I get and error telling me that the token is undefined.
            //If I run the code from inside a $timeout works as I need...

        })
        .error(function(data){
             alert('error');
        });

我也尝试在 $scope.$apply 中 运行 但我收到一个错误提示 $digest already in progress

我要调用的非angularjs库很简单就两行

var settings = {} 
LibraryCall(settings);

如何立即更新模型?

为简洁起见,我删除了错误回调,请勿在您的代码中这样做:)

我想你调用的代码是异步的,如果不是,你不应该有任何 $scope 更新问题(因为所有 angular promises 已经调用 $apply)...

这应该有效:

$http.post('https://example.org', obj).success(function(data){
    $scope.personaltoken = data.token;

    otherLibrary.doSomething(data.token, function(error, result) {
        $scope.changeSomething = 'toHey';
        $scope.$apply();
    });
});

这也应该有效:

$http.post('https://example.org', obj).success(function(data){
    $scope.personaltoken = data.token;

    otherLibrary.doSomething(data.token, function(error, result) {
        $scope.$apply(function() {
            $scope.changeSomething = 'toHey';
        });
    });
})

这应该引发 $digest already in progress 错误,因为 $http 确实已经将 promise 回调包装在 $apply 调用上。

$http.post('https://example.org', obj).success(function(data){
    $scope.personaltoken = data.token;
    $scope.$apply(function() {
        otherLibrary.doSomething(data.token, function(error, result) {
            $scope.changeSomething = 'toHey';
        });
    });
})

尝试使用 $scope.$evalAsync() 或 $scope.$applyAsync()。 它们是为这样的东西而制作的。它将稍后及时执行代码。与 $timeout 没有太大区别,但可能更快。

$scope.$evalAsync(function(){
    var settings = {} 
    LibraryCall(settings);
})

编辑:引用 Ben Nadel 关于 $timeout 和 $evalAsync 之间的区别,来自 this post:

So, in essence, $scope.$evalAsync() combines the best of both worlds: When it can (which is most of the time), it will evaluate your expression in the same tick; otherwise, it will evaluate your expression in a later tick, which is exactly what $timeout() is doing.

我尝试按照@Kjell 的建议使用$scope.$evalAsync,但没有用。

阅读了有关 $scope 的更多信息后,我找到了我需要的东西。

$scope.$applyAsync(function(){
    var settings = {} 
    LibraryCall(settings);
});

$scope.$applyAsync 将安排稍后调用 $apply。

https://docs.angularjs.org/api/ng/type/$rootScope.Scope