网站搜索

javascript - $http promise 链以错误顺序运行


我刚接触 AngularJS。我的目标非常简单。我想进行一次 Ajax 调用以获取数据,并且在完成后,我想进行第二次调用以获取另一组依赖于第一组信息的数据。

我正在尝试使用 Promise 机制来实现这一点,这样我就可以利用链式调用而不是嵌套的 ajax 调用,并且更好地保留独立函数的能力,以便根据需要将它们连接在一起。

我的代码如下所示:

var promiseGetWorkTypes = function ($q, $scope, $http) {
	console.log("promiseGetWorkTypes");

	return $q(function (resolve, reject) {
		$http({
			method: 'GET',
			url: '/WorkTypes'
		}).then(
			function (payload) {
				console.log("Got workttypegroups")
				console.log(payload);

				$scope.WorkTypeGroups = payload.data;

				console.log("End of worktypegroups");
				resolve(payload);
			},
			function (payload) {
				reject(payload);
			});
	});
};

var promiseGetRecentActivities = function ($q, $scope, $http) {
	console.log("promiseGetRecentActivities");

	return $q(function (resolve, reject) {
		$http({
			method: 'GET',
			url: '/RecentHistory'
		}).then(
			function (payload) {
				$scope.RecentActivities = payload.data;

				resolve(payload);
			},
			// data contains the response
			// status is the HTTP status
			// headers is the header getter function
			// config is the object that was used to create the HTTP request
			function (payload) {
				reject(payload);
			});
	});
};

var index = angular.module("index", []);

index
.controller('EntitiesController', function ($scope, $http, $timeout, $q) {
	promiseGetWorkTypes($q, $http, $scope)
		.then(promiseGetRecentActivities($q, $http, $scope));
}

然而,当我查看调试控制台时,我看到对“promiseGetRecentActivities”的调用在对“promiseGetWorkTypes”的Ajax处理调用发生之前就开始了。

我在这里遗漏了什么或做错了什么?

答案#1

当你写作时

promiseGetWorkTypes($q, $http, $scope).then(promiseGetRecentActivities($q, $http, $scope));

当评估此行时,会调用 promiseGetActivites。你应该能够将对 promiseGetActivities 的调用包装在另一个函数中,以延迟调用,直到第一个 promise 已解析,从而使调用按顺序运行:

promiseGetWorkTypes($q, $http, $scope).then(function() {
  promiseGetRecentActivities($q, $http, $scope);
});

原因与 then 内发生的事情无关,而是由于 JavaScript 语法。如下所示:

myFunc1(myFunc2());

将调用 myFunc2() 的 结果 传递给 myFunc1,而不是对 myFunc2 函数的引用。因此,从逻辑上讲,myFunc2 必须在 myFunc1 之前运行。如果你写

myFunc1(myFunc2);

那么 myFunc1 将接收到 myFunc2 的引用,因此 myFunc1 会在 myFunc2 之前运行(实际上,myFunc2 只有在 myFunc1 内部的某处有调用它的代码时才会运行)。

以内联/匿名方式定义函数并不会改变这种行为。要将匿名函数的结果传递给另一个函数,你可以这样做

myFunc1((function() {
  return 'something';
})());

这将首先评估匿名函数,因为它的返回值 'something' 将被传递给 myFunc1。要传递匿名函数的引用,你可以这样做:

myFunc1(function() {
  return 'something';
});

然后是否会调用传递给它的函数,就取决于 myFunc1 了。

回到你的问题,你的代码:

promiseGetWorkTypes($q, $http, $scope).then(promiseGetRecentActivities($q, $http, $scope));

正在将 promiseGetRecentActivities($q, $http, $scope) 的结果传递给 then,因此它必须在 then 运行之前执行,因此当然不会等待 promiseGetWorkTypes 的 promise 被解析。你似乎想要的是传递给它一个函数,当调用该函数时,执行 promiseGetRecentActivities($q, $http, $scope),这正是

promiseGetWorkTypes($q, $http, $scope).then(function() {
  promiseGetRecentActivities($q, $http, $scope);
});

做

作为附带说明,把 $q、$http 等传递给各个函数似乎有点不寻常/过于复杂,但我认为讨论替代方案可能超出了这个问题的范围。