web-dev-qa-db-ja.com

Angular 2 $ timeoutと同等

Angular 2環境で(大量の)既存のコードを使用する必要があります。そのコードは、AngularJS 1.xの $timeoutサービス を広範囲に使用しています。コードで使用される他のさまざまなAngularJS 1.xサービスとは対照的に、$timeoutサービスに相当するAngular 2に関する情報を見つけるのに苦労しています。

Angular docs には、名前にtimeout- somethingが含まれるサービスの言及が含まれていないようです。記事 AngularJS からのアップグレードでは、私が直面しているシナリオに言及しています:

$location$timeoutなどのAngularJSの組み込みサービスにアクセスしたい場合があります。

残念なことに、この記事では実際にそれらの特定のサービスにアクセスする方法を説明していません。後続の例HeroesServiceは、AngularJS 1.xによって提供される依存関係のないサービスを想定しています。

this one などの記事は、ネイティブ setTimeout function を使用することを提案していますが、$timeoutサービスの機能にも対応していません。

Angular 2環境で$timeout機能を再現するにはどうすればよいですか?

編集:回答で指摘されているように、Angular 2.を使用する場合、ネイティブのsetTimeout関数の欠点は関係ありません。その場合、完全な$q AngularJS 1.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;
}
24
O. R. Mapper

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で変更検出を開始します。これは ダイジェストの拡張バージョンの種類 です。

$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);