无法在两个JavaScript函数之间使用sleep函数。

4
我正在尝试创建一个 Angular 表单,在此表单中,用户键入文本时,在其下方的文本标签中显示“用户正在输入...”。
然后,它等待 200 毫秒,文本标签变为空白(“用户正在输入...”消失)。
我使用了 Angular ng-change 指令来实现。我的代码如下。
问题在于,由于某种原因,我编写的帮助方法在运行两个方法之间进行等待时出现了问题。由于某种原因,“用户正在输入...”文本无法在短暂等待后消失。
为什么会这样呢?
谢谢。

angular.module('myApp', [])
.controller('myCtrl', ['$scope', function($scope) {
  $scope.count = 0;
  $scope.myFunc = function() {
    runTwoFunctionWithSleepBetweenThem(function (){$scope.text='user is typing...';},function (){$scope.text='';},200);
  };

  var runTwoFunctionWithSleepBetweenThem = function(foo1,foo2, time) {
    var sleep =function (time) {
      return new Promise((resolve) => setTimeout(resolve, time));
    }
    foo1();
    sleep(time).then(() => {
      foo2();
    });
  }
}]);
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="myApp">
  <div ng-controller="myCtrl">
    <p>Write something in the input field:</p>
    <input type="text" ng-change="myFunc()" ng-model="myValue" />
    <p>{{text}}</p>
  </div>
</body>
</html>


1
似乎与您的代码在超时执行时超出了Angular范围有关,请尝试在计时器回调中使用$scope.$apply... - user4615488
1
我不确定,但我认为你需要调用 $scope.$apply() 以便使 $scope.text 变量的更改生效。 - Titus
3个回答

3

正如André Vale和Titus在评论中提到的,您已经超出了应用程序循环范围,因此在更新作用域后,Angular不知道要进行“脏检查”。

var runTwoFunctionWithSleepBetweenThem=function(foo1,foo2, time) {
  var sleep = function (time) {
    return new Promise((resolve) => setTimeout(resolve, time));
  }
  foo1();
  sleep(time).then(() => {
    foo2();
    $scope.$apply();
  });
}

您的sleep函数近似于$timeout,它是基于Promise的;您可以轻松地切换到它,并利用它默认在$apply块内调用函数的优势:

// Inject the $timeout service in your controller.
var runTwoFunctionWithSleepBetweenThem=function(foo1, foo2, time) {
  foo1();
  $timeout(foo2, time);
}

如果您想使此代码完全兼容 Promise,如果 foo1 返回一个 promise,就延迟它,如果它被拒绝,则中止,那么您可以将其重新表达为以下形式:
// Inject $timeout and $q.
var runTwoFunctionWithSleepBetweenThem=function(foo1, foo2, time) {
  $q.when(foo1()).then(() => $timeout(foo2, time));
}

1
如果您愿意使用下划线,请查看 _.debounce。此外,人们对于 $scope.$apply() 是正确的。

var time = 200;
var func2 = _.debounce(function(){
  $scope.text = "";
  $scope.$apply();
}, time);
$scope.myFunc = function() {
  $scope.text='user is typing...';
  func2();
};


1
你可以为这个行为定义服务:
app.service('Sleep', Sleep);
Sleep.$inject = [$timeout]

function Sleep($timeout) {
  return time =>new Promise((ok) => {$timeout(ok, time);});
}

使用方法(在将 Sleep 服务注入为 sleep 后):

foo1();
sleep(1000).then(foo2);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接