Angular 2 相当于 $timeout
Posted
技术标签:
【中文标题】Angular 2 相当于 $timeout【英文标题】:Angular 2 equivalent for $timeout 【发布时间】:2018-01-24 15:45:35 【问题描述】:我必须在 Angular 2 环境中使用(大量)现有代码。该代码广泛使用了 AngularJS 1.x 中的$timeout
service。与代码中使用的各种其他 AngularJS 1.x 服务相反,我很难找到有关 $timeout
服务的 Angular 2 等效项的信息。
Angular docs 似乎没有提到任何名称中带有timeout
-something 的服务。文章Upgrading from AngularJS 确实提到了我面临的情况:
也许您想访问 AngularJS 的内置服务,例如
$location
或$timeout
。
不幸的是,这篇文章实际上并没有解释如何访问这些特定服务,因为后续示例 HeroesService
假定服务没有 AngularJS 1.x 提供的任何依赖项。
this one 等文章建议使用原生的setTimeout
function 也不符合$timeout
服务的功能。
如何在 Angular 2 环境中重现 $timeout
功能?
编辑:正如答案中所指出的那样,使用 Angular 2 时,本机 setTimeout
函数的缺点是不相关的。在这种情况下,如果我有来自 AngularJS 1.x 的完整 $q
,我可以大致如下复制$timeout
函数:
function $timeout(fn, delay)
var result = $q.defer();
setTimeout(function ()
$q.when(fn()).then(function (v)
result.resolve(v);
);
, delay);
return result.promise;
【问题讨论】:
blog.neilni.com/2016/03/27/settimeout-in-angular-2 ***.com/a/44096451/8317956 @slacker:delay
运算符似乎返回了 Observable
,所以我必须摆脱它才能将事情提升到正确的承诺。不过,带有指向计时器的指针的第一个链接看起来很有希望;也许我可以在此基础上制作一个看起来像原始 $timeout
的包装器。我只是想知道,为什么我在Angular docs 中找不到timer
?
【参考方案1】:
使用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);
【讨论】:
“为什么让你这么说?” - 好吧,链接的文章强调了一些需要 Angular 消化的超时后做事的注意事项。 无论如何,我不知道如何使用setTimeout
来创建类似$timeout
的东西。我想收回一个承诺,所以在 AngularJS 1.x 中,我可能需要创建一个 deferred 并在传递给setTimeout
的函数中解决它。问题是,Angular 2 中也缺少$q.defer()
。
@O.R.Mapper,你提到的那篇文章谈到了AngularJS上下文的差异。它所说的不适用于Angular。 Angular 使用zone.js
拦截异步操作并运行摘要
我已经更新了我的问题以包含一个重新创建 $timeout
功能的示例。
@O.R.Mapper,我已将实现添加到我的答案中。以上是关于Angular 2 相当于 $timeout的主要内容,如果未能解决你的问题,请参考以下文章