web-dev-qa-db-fra.com

Angular 2 équivalent pour $ timeout

Je dois utiliser (de grandes quantités) de code existant dans un environnement Angular 2. Ce code utilise beaucoup de $timeout service d’AngularJS 1.x. Contrairement à divers autres services AngularJS 1.x utilisés dans le code, j'ai du mal à trouver des informations sur un Angular 2 équivalent pour le $timeout un service.

Les documents angulaires ne semblent pas contenir de mention d'un service avec timeout- quelque chose dans son nom. L'article Mise à niveau de AngularJS ) == mentionne le scénario auquel je suis confronté:

Peut-être souhaitez-vous accéder aux services intégrés d’AngularJS tels que $location ou $timeout.

Malheureusement, l'article n'explique pas réellement comment accéder à ces services particuliers, car l'exemple suivant HeroesService suppose un service sans aucune dépendance fournie par AngularJS 1.x.

Des articles tels que celui-ci suggèrent d'utiliser la fonction native setTimeout fonction ne correspond pas aux capacités du $timeout services, soit.

Comment puis-je reproduire le $timeout Fonctionnalités dans l’environnement Angular 2??

EDIT: Comme il a été noté dans les réponses, les inconvénients de la fonction native setTimeout ne sont pas pertinents lors de l’utilisation de Angular 2. Dans ce cas, si j’avais la totalité de $q de AngularJS 1.x, je pourrais reproduire le $timeout fonctionne à peu près comme ceci:

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

Utilisez la fonction native setTimeout. Il n’est plus nécessaire d’utiliser des services spéciaux dans Angular. Cela est dû à l’introduction de zones , plus précisément NgZone .

Des articles tels que celui-ci suggèrent que l'utilisation de la fonction native setTimeout ne soit pas à la hauteur des capacités des services $ timeout.

Pourquoi vous le dites? La tâche principale de $timeout Le service devait commencer à résumer après l’exécution de la fonction retardée. Vous pouvez le voir depuis les sources:

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

Dans Angular zone.js intercepte toutes les opérations asynchrones et lance la détection des modifications dans Angular qui est sorte de version améliorée de digest .

Si vous devez répliquer le $timeout, vous pouvez approximativement le faire comme ceci:

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