$ timeout等效于$ timeout

时间:2017-08-16 13:12:52

标签: javascript angular timeout

我必须在Angular 2环境中使用(大量)现有代码。该代码广泛使用了AngularJS 1.x中的$timeout service。与代码中使用的各种其他AngularJS 1.x服务相反,我很难找到有关$timeout服务的Angular 2等效信息。

Angular docs似乎没有提及timeout的服务 - 名称中包含某些内容。文章Upgrading from AngularJS确实提到了我面临的情景:

  

也许您想要访问AngularJS的内置服务,例如$location$timeout

不幸的是,本文并未实际解释如何访问这些特定服务,因为后续示例HeroesService假定服务没有AngularJS 1.x提供的任何依赖项。

诸如this one之类的文章建议使用原生setTimeout function不符合$timeout服务的功能。

如何在Angular 2环境中重现$timeout功能?

编辑:正如在答案中已经注意到的,当使用Angular 2时,原生setTimeout函数的缺点是无关紧要的。在这种情况下,如果我从AngularJS 1获得了完整的$q。 x,我可以大致像这样复制$timeout函数:

function $timeout(fn, delay) {
    var result = $q.defer();
    setTimeout(function () {
        $q.when(fn()).then(function (v) {
            result.resolve(v);
        });
    }, delay);
    return result.promise;
}

1 个答案:

答案 0 :(得分:9)

使用setTimeout原生函数。不再需要在Angular中使用特殊服务。这是由于引入了zones,特别是NgZone

  

这样的文章建议使用本机setTimeout函数   也不辜负$ timeout服务的功能。

为什么让你这么说? $timeout服务的主要任务是在执行延迟函数后开始摘要。你可以从消息来源看到它:

function $TimeoutProvider() {
  this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
    function($rootScope,   $browser,   $q,   $$q,   $exceptionHandler) {

        timeoutId = $browser.defer(function() {
          try {
            deferred.resolve(fn.apply(null, args));
          } catch (e) {
          ...

          if (!skipApply) $rootScope.$apply();  <-------------------- here
        }, delay);

在Angular zone.js中拦截所有异步操作并开始在Angular中更改检测kind of enhanced version of digest

如果你需要复制$timeout,你可以大致这样做:

function $timeout(fn, delay, ...args) {
  let timeoutId;

  $timeout.cancel = $timeout.cancel || function (promise) {
    if (promise && promise.$$timeoutId in $timeout.promises) {
      $timeout.promises[promise.$$timeoutId][1]('canceled');
      delete $timeout.promises[promise.$$timeoutId];
      return clearTimeout(promise.$$timeoutId);
    }
    return false;
  };

  $timeout.promises = $timeout.promises || {};

  const promise = new Promise((resolve, reject) => {
    timeoutId = setTimeout(function () {
      try {
        resolve(fn.apply(null, args));
      } catch (e) {
        reject(e);
      } finally {
        delete $timeout.promises[promise.$$timeoutId];
      }
    }, delay);

    $timeout.promises[timeoutId] = [resolve, reject];
  });

  promise.$$timeoutId = timeoutId;

  return promise;
}

// some basic testing

$timeout((v) => {
  console.log('a', v);
}, 2000, 7);

const promise = $timeout(() => {
  console.log('b');
}, 3000);

promise.catch((reason) => {
  console.log(reason);
});

$timeout.cancel(promise);