Угловой 2 эквивалент для $ timeout

Я должен использовать (большой объем) существующий код в среде Angular 2. Этот код широко использует услугу $timeout от AngularJS 1.x. В отличие от других других услуг AngularJS 1.x, которые используются в коде, мне сложно найти информацию об эквиваленте Angular 2 для службы $timeout.

Угловые документы, похоже, не содержат упоминаний о службе с timeout -something в ее имени. В статье " Обновление от AngularJS" упоминается сценарий, с которым я сталкиваюсь:

Возможно, вам нужен доступ к встроенным сервисам AngularJS, таким как $location или $timeout.

К сожалению, статья на самом деле не объясняет, как получить доступ к этим конкретным службам, так как следующий пример HeroesService принимает сервис без каких-либо зависимостей, предоставляемых AngularJS 1.x.

Такие статьи, как эта предлагают использовать родную setTimeout функцию не оправдают возможности $timeout услуг, либо.

Как я могу воспроизвести функции $timeout в среде Angular 2?

EDIT: Как было отмечено в ответах, недостатки встроенной функции setTimeout не имеют значения при использовании Angular 2. В этом случае, если бы у меня был полный $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;
}

Ответ 1

Используйте встроенную функцию setTimeout. Больше нет необходимости использовать специальные услуги в Angular. Это связано с внедрением зон, в частности, 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);