Ответ 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);