Javascript 用fetchapi替换$http
我正在用Fetch API替换Javascript 用fetchapi替换$http,javascript,angularjs,angular-promise,fetch-api,angularjs-http,Javascript,Angularjs,Angular Promise,Fetch Api,Angularjs Http,我正在用Fetch API替换$http,并用Promise API替换$q。正因为如此,Angular不再运行摘要循环,因此UI不再呈现。为了解决这个问题,我尝试了Zone.js,这似乎部分解决了我们的问题。不幸的是,它的API在0.6中完全改变了,所以我们使用了 现在谈谈实际问题 刷新页面时,Angular会按预期配置和引导应用程序。在此阶段,我将初始化区域并装饰$rootScope.apply区域和$rootScope.$digest()。现在,当我在状态/路由之间转换(使用ui路由器)时
$http
,并用Promise API替换$q
。正因为如此,Angular不再运行摘要循环,因此UI不再呈现。为了解决这个问题,我尝试了Zone.js,这似乎部分解决了我们的问题。不幸的是,它的API在0.6中完全改变了,所以我们使用了
现在谈谈实际问题
刷新页面时,Angular会按预期配置和引导应用程序。在此阶段,我将初始化区域并装饰$rootScope.apply
区域和$rootScope.$digest()
。现在,当我在状态/路由之间转换(使用ui路由器)时,一切都按预期工作,但当完全刷新时,会出现竞争条件,区域/摘要无法正确运行。我不知道怎么修
我在angular.run()块中有以下代码:
console.log('Zone setup begin');
const scopePrototype = $rootScope.constructor.prototype;
const originalApply = scopePrototype.$apply;
const zoneOptions = {
afterTask: function afterTask() {
try {
$rootScope.$digest();
} catch (e) {
$exceptionHandler(e);
throw e;
}
}
};
scopePrototype.$apply = function $applyFn() : void {
const scope = this;
const applyArgs = arguments;
window.zone.fork(zoneOptions).run(() => {
originalApply.apply(scope, applyArgs);
console.log('Zone + $digest run!');
});
};
console.log('Zone setup end');
在上面,您可以看到,当区域初始化开始、结束和运行(+角度摘要周期)时,我会登录到控制台。在通过FetchAPI获取数据的控制器中,我添加了一个console.log('datafetched!')代码>这样我就知道什么时候提取了数据
现在,控制台中的输出:
使用ui路由器进行状态转换(工作正常)
请注意,摘要最后运行
Zone setup begin
Zone setup end
Zone + $digest run!
Zone + $digest run!
Zone + $digest run!
Zone + $digest run!
Data fetched!
Zone + $digest run!
状态/路由的完全刷新(最后不运行)
正如您所见,区域/摘要在获取数据后不会运行,这就是数据和UI不会呈现在页面上的原因。将由创建的ES6承诺转换为AngularJS$q承诺
使用$q.when
将ES6承诺转换为AngularJS承诺
AngularJS通过提供自己的事件处理循环来修改正常的JavaScript流。这将JavaScript分为经典和AngularJS执行上下文。只有在AngularJS执行上下文中应用的操作才会受益于AngularJS数据绑定、异常处理、属性监视等。。。由于承诺来自AngularJS框架之外,因此该框架不知道对模型的更改,也不更新DOM
使用$q.when
将外部承诺转换为角度框架承诺:
var myRequest = new Request('flowers.jpg');
$q.when(fetch(myRequest)).then(function(response) {
//code here
})
使用与AngularJS框架及其摘要周期正确集成的$q服务承诺
$q.when
将可能是值或(第三方)的对象包装为$q
承诺。当您处理的对象可能是承诺,也可能不是承诺,或者承诺来自不可信任的来源时,这非常有用
根本原因
包装$q.when
会起作用,但根据我的团队经验,包装非常挑剔,而且容易出错。例如,从承诺的主体内部返回$q.when
时,
函数仍将作为常规的承诺
链接,并且在回调时不会得到$digest
它还要求所有作者理解两个外观非常相似的构造(Promise/$q)之间的区别,并关心异步调用的每一级的具体类型。如果您使用的是像async
/await
(它进一步抽象了承诺类型)这样的现代便利设备,那么您将遇到更多的麻烦。突然之间,您的代码中没有一个是框架无关的
我们的团队认为,值得投入一个大补丁来确保所有承诺(以及async
/await
关键字)“只起作用”,而无需额外考虑
丑陋?对但我们觉得这是一个不错的折衷方案
修补程序承诺回调以始终应用$rootScope
首先,我们针对Promise
在angular.run
块中安装修补程序:
console.log('Zone setup begin');
const scopePrototype = $rootScope.constructor.prototype;
const originalApply = scopePrototype.$apply;
const zoneOptions = {
afterTask: function afterTask() {
try {
$rootScope.$digest();
} catch (e) {
$exceptionHandler(e);
throw e;
}
}
};
scopePrototype.$apply = function $applyFn() : void {
const scope = this;
const applyArgs = arguments;
window.zone.fork(zoneOptions).run(() => {
originalApply.apply(scope, applyArgs);
console.log('Zone + $digest run!');
});
};
console.log('Zone setup end');
angular.module(…).run(normalizepromissesideeffects);
normalizepromissesideeffects.$inject=['$rootScope'];
函数normalizepromissesideeffects($rootScope){
附件适用于承诺方法(“then”);
附件适用于承诺方法(“捕获”);
附件适用于承诺方法(“最终”);
函数AttachScopeApplicationPromiseMethod(方法名){
const NativePromiseAPI=window.Promise;
const nativeImplementation=NativePromiseAPI.prototype[methodName];
NativePromiseAPI.prototype[methodName]=函数(…promiseArgs){
const newPromiseArgs=promiseArgs.map(wrapFunctionInScopeApplication);
return nativeImplementation.bind(this)(…新承诺人);
};
}
函数包装FunctionInscope应用程序(fn){
如果(!isFunction(fn)| fn.isScopeApplicationWrapped){
返回fn;
}
常量wrappedFn=(…参数)=>{
const result=fn(…args);
//之所以使用此API,是因为在AngularJS src中使用了$q
$rootScope.$evalAsync();
返回结果;
};
wrappedFn.isScopeApplicationWrapped=true;
返回包装n;
}
}
异步/等待
如果您想支持使用async
/await
,您还需要将Babel配置为始终按照承诺实现语法。我们使用了。问题不包含plunk或有助于调试问题的内容,这是必须的$应用补丁看起来很可疑。从$q和$http切换到本机承诺和获取的原因是什么?您可以有效地消除Angular作为框架的一系列好处,并创建一系列问题。这看起来不是一个好的折衷方案。那是因为我无法复制这个。从$q和$http切换到本机promises和Fetch的原因是,最终目标是用React替换Angular。ui路由器(我们用于路由)现在支持路由到反应组件。一般来说,我建议避免隐性消化,因为它们会导致无法控制的混乱和糟糕的表现。合理的中间解决方案是创建