强制代码在JavaScript

时间:2015-08-09 22:24:19

标签: javascript angularjs node.js sockets socket.io

Angular.jsSocket.io应用中,我希望在通过Socket.io发送图片之前显示加载。我写这段代码:

当点击一个按钮时,这个代码会运行,首先我要运行startLoading函数,之后我想发送图像:

$scope.startLoading(function(){
      $scope.socket.emit('sendImg', {
            data: $scope.newImg,
      });
});

这是我的startLoading函数:

$scope.startLoading = function (callback) {
    //DO SOME STUFF LIKE ENABLING LOADING ANIMATION
    $scope.animation =true; //binded to UI
    $scope.errors = false; //binded to UI

    callback(); //it seems this code runs before above lines
};

但似乎callback()行在前两行之前运行,因此,我的加载在将图像发送到服务器后出现!为什么?我将回调线更改为这样的超时并且它工作正常,但这是一个很好的解决方案吗?我不这么认为!我需要为标准代码做些什么?

$scope.startLoading = function (callback) {
    //DO SOME STUFF LIKE ENABLING LOADING ANIMATION
    $scope.animation =true; //binded to UI
    $scope.errors = false; //binded to UI

    $timeout(function(){callback();}, 1000);
};

实际上,代码按顺序运行但是调用回调并发送图像冻结页面,因此,我的加载在冻结结束后出现。但我需要在冻结之前加载开始

1 个答案:

答案 0 :(得分:1)

您的代码确实按顺序运行,但前两行不会立即更改UI。

当您为范围变量分配一些值时,它只是一个变量赋值。它不会触发任何事件。 Angular只会在以后评估绑定并查找更改时更新UI。所以这是发生的事情:

$scope.startLoading = function (callback) {

    // Presumably this is called from some event from Angular, 
    // so all this is run in an $apply, in an Angular "context".
    // But this is still "plain" javascript, so the next two lines
    // are just plain variable assignments.

    $scope.animation =true;
    $scope.errors = false;

    callback();  // This function does its thing, then returns

    // When this function returns, Angular will evaluate all of its
    // bindings, will find that the above values have changed,
    // and will update the DOM.
};

有关详细信息,请参阅"与浏览器事件循环集成" dev guide中的部分。

您想要的是确保在回调运行之前更新DOM。我认为使用$timeout对此没有任何不妥。 可能有更好/更好的方式,但我还没有找到它......

所以它会变成这样:

$scope.startLoading = function (callback) {
    $scope.animation =true;  // at this point, these are just
    $scope.errors = false;   // plain variable assignments

    $timeout(callback);  // schedule callback to run later

    // After this returns, Angular will evaluate its bindings,
    // and update the DOM, so if $scope.animation and $scope.errors
    // are bound to something, they can trigger some visible change.

    // callback will be called in the next $digest cycle, so _after_
    // the DOM has been updated
};

(如果您只想在下一个" tick"中运行它,则无需为超时指定值。此外,无需包装回调,它可以直接传递给$timeout。)

希望这有帮助!