AngularJS: $q.defer() 不能被工厂方法共享
AngularJS: the $q.defer() cannot be shared by factory methods
在我的 web 应用程序中,我编写了一个工厂方法,用于使用 $q
服务提供 ajax 调用和返回承诺。您可能会说,我仍处于使用 AngularJS; 的学习曲线上。我在 $q.defer() 对象上发现了一些有趣的东西,它不能被工厂方法共享。我在工厂组件 (plnker here) 中编写了以下假 ajax 调用:
(function() {
'use strict';
angular.module('testAjax')
.factory('AjaxPromiseService', AjaxPromiseService);
AjaxPromiseService.$inject = ['$q', '$timeout'];
function AjaxPromiseService($q, $timeout) {
//var deferred = $q.defer(); //cannot be claimed for sharing here
var methodObj = {getDummyData : getDummyData,
getName: getName
};
return methodObj;
/******************** implementations below **********/
function getDummyData() {
var data = {"data" : "dummy data from ajax!"};
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(data);
}, 3000); //3 seconds
return deferred.promise;
} //getDummyData
function getName() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve({"name": "my name is john doe!"});
}, 2000); //2 seconds
return deferred.promise;
} //getName
}
}());
在我的控制器中,我有以下内容:
(function() {
'use strict';
angular.module('testAjax', ['ui.router', 'Constants'])
.controller('testController', testController);
testController.$inject = ['$log', 'AjaxPromiseService', '$http', '$q', 'URL_CONFIGS'];
function testController($log, AjaxPromiseService, $http, $q, URL_CONFIGS) {
$log.info('in the testController');
var vm = this;
vm.message = URL_CONFIGS.home;
vm.getData = function() {
AjaxPromiseService.getDummyData().then(function(data) {
vm.message += data.data;
//$log.info($q);
}).catch(function(err) {
$log.info('error in getting data');
}).finally(function() {
$log.info('getData is completed');
}); //getDummyData
}; //getData
vm.getName = function() {
AjaxPromiseService.getName().then(function(data) {
vm.message += data.name;
//$log.info($q);
}).catch(function(err) {
$log.info('error in getting data');
}).finally(function() {
$log.info('getData is completed');
}); //getDummyData
}; //getName
}
}());
在我的模板中,我有以下两个按钮调用控制器中的上述两个功能。
<button class="btn btn-primary" ng-click="contentView.getData()">Get data</button>
<button class="btn btn-primary" ng-click="contentView.getName()">Get name</button>
<strong>Message: {{contentView.message}}</strong>
在工厂AjaxPromiseService组件中,var deferred
对象不能在工厂内部的两个函数之间共享,我必须定义一个 deferred 每个函数的对象,否则无法运行。 所以我想知道为什么 deferred
不能在工厂方法之间共享?
Why deferred
cannot be shared between methods?
因为 Deferred 对象链接到它解析的 promise。每个承诺都需要一个。如果您共享一个延迟,每个方法都会 return 相同的承诺。
另见 What are the differences between Deferred, Promise and Future in JavaScript?。
实际上您可以共享延迟对象。只是不要把它当作一个服务,而是一个简单的 JS 对象。一个延迟对象只能被解析一次,这是有目的的。在您的 AjaxPromiseService 中,您显然需要两个不同的延迟,因为您使用不同的数据解析它们。
例如,$http.post()
每次returns个不同的延迟对象
当您的延迟可以从不同来源解决时(例如,您尝试同时从 localStorage 缓存、http 源和一些正在计算此数据的 WebWorker 获取一些数据),在多个函数之间共享一个延迟是很有用的。 =11=]
如果我对你的理解是正确的,你想重用由 $q.defer() 创建的同一个对象。
$q.defer() returns 一个将在未来某个时间通过调用 .resolve 方法解析的对象。所以基本上它代表了将在未来某个时刻完成的某个动作。
您不能为将来完成的多个操作共享同一个承诺对象。
另请参阅 Bergi 的回复中的 link。
你也坏了,因为
var methodObj = {getDummyData : getDummyData};
缺少 getName 我修复了它 in this plunker
在我的 web 应用程序中,我编写了一个工厂方法,用于使用 $q
服务提供 ajax 调用和返回承诺。您可能会说,我仍处于使用 AngularJS; 的学习曲线上。我在 $q.defer() 对象上发现了一些有趣的东西,它不能被工厂方法共享。我在工厂组件 (plnker here) 中编写了以下假 ajax 调用:
(function() {
'use strict';
angular.module('testAjax')
.factory('AjaxPromiseService', AjaxPromiseService);
AjaxPromiseService.$inject = ['$q', '$timeout'];
function AjaxPromiseService($q, $timeout) {
//var deferred = $q.defer(); //cannot be claimed for sharing here
var methodObj = {getDummyData : getDummyData,
getName: getName
};
return methodObj;
/******************** implementations below **********/
function getDummyData() {
var data = {"data" : "dummy data from ajax!"};
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(data);
}, 3000); //3 seconds
return deferred.promise;
} //getDummyData
function getName() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve({"name": "my name is john doe!"});
}, 2000); //2 seconds
return deferred.promise;
} //getName
}
}());
在我的控制器中,我有以下内容:
(function() {
'use strict';
angular.module('testAjax', ['ui.router', 'Constants'])
.controller('testController', testController);
testController.$inject = ['$log', 'AjaxPromiseService', '$http', '$q', 'URL_CONFIGS'];
function testController($log, AjaxPromiseService, $http, $q, URL_CONFIGS) {
$log.info('in the testController');
var vm = this;
vm.message = URL_CONFIGS.home;
vm.getData = function() {
AjaxPromiseService.getDummyData().then(function(data) {
vm.message += data.data;
//$log.info($q);
}).catch(function(err) {
$log.info('error in getting data');
}).finally(function() {
$log.info('getData is completed');
}); //getDummyData
}; //getData
vm.getName = function() {
AjaxPromiseService.getName().then(function(data) {
vm.message += data.name;
//$log.info($q);
}).catch(function(err) {
$log.info('error in getting data');
}).finally(function() {
$log.info('getData is completed');
}); //getDummyData
}; //getName
}
}());
在我的模板中,我有以下两个按钮调用控制器中的上述两个功能。
<button class="btn btn-primary" ng-click="contentView.getData()">Get data</button>
<button class="btn btn-primary" ng-click="contentView.getName()">Get name</button>
<strong>Message: {{contentView.message}}</strong>
在工厂AjaxPromiseService组件中,var deferred
对象不能在工厂内部的两个函数之间共享,我必须定义一个 deferred 每个函数的对象,否则无法运行。 所以我想知道为什么 deferred
不能在工厂方法之间共享?
Why
deferred
cannot be shared between methods?
因为 Deferred 对象链接到它解析的 promise。每个承诺都需要一个。如果您共享一个延迟,每个方法都会 return 相同的承诺。
另见 What are the differences between Deferred, Promise and Future in JavaScript?。
实际上您可以共享延迟对象。只是不要把它当作一个服务,而是一个简单的 JS 对象。一个延迟对象只能被解析一次,这是有目的的。在您的 AjaxPromiseService 中,您显然需要两个不同的延迟,因为您使用不同的数据解析它们。
例如,$http.post()
每次returns个不同的延迟对象
当您的延迟可以从不同来源解决时(例如,您尝试同时从 localStorage 缓存、http 源和一些正在计算此数据的 WebWorker 获取一些数据),在多个函数之间共享一个延迟是很有用的。 =11=]
如果我对你的理解是正确的,你想重用由 $q.defer() 创建的同一个对象。
$q.defer() returns 一个将在未来某个时间通过调用 .resolve 方法解析的对象。所以基本上它代表了将在未来某个时刻完成的某个动作。
您不能为将来完成的多个操作共享同一个承诺对象。 另请参阅 Bergi 的回复中的 link。
你也坏了,因为
var methodObj = {getDummyData : getDummyData};
缺少 getName 我修复了它 in this plunker