q 承诺在完成之前解决?
q promise resolved before completed?
我想我可能遗漏了一些关于 promise 如何运作的基本知识,因为我似乎从来没有得到我期望的结果,所以希望有人能纠正我的想法。
在这种情况下,这是一个相对容易的调用。我有一个 angular 工厂,除其他外,它从 API(调用 mongodb)获取一些数据。
由于有一个 $http 请求(异步),我将 http 调用包装在一个 $q 函数中,如果成功,该函数应该 return 一个 resolve
,如果一个错误则应该 reject
。
factory.loadLayout = function (layoutName) {
return $q(function(resolve, reject){
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
resolve('OK');
})
.error(function(data,status,headers,config){
reject(new Error( status));
});
});
}
然后我有另一个函数,它依赖于第一个函数中收集的数据,称为 getButtonId,但据我所知,即使它包含在 .then
中,它似乎它在承诺解决之前被调用。
var promise = padArea.loadLayout(layoutName);
promise.then(padArea.getButtonId('A0'));
那我错过了什么?
==更新==
所以使用 q.defer
尝试同样的事情
factory.loadLayout = function (layoutName) {
var defer = $q.defer()
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
defer.resolve('OK');
})
.error(function(data,status,headers,config){
defer.reject(new Error( status));
});
return defer.promise;
}
仍然没有像我预期的那样工作,.then 中的函数仍然在 http 完成之前被调用。
== 更新 2 ==
好的,它开始工作了(如果我只是在 .then 中调用工厂中的函数,它会直接调用它,但是,如果我将它包装在下面的函数中,它会突然起作用。谁能解释为什么,因为对我来说,将对函数的调用包装在函数内与仅调用函数没有区别。
padArea.loadLayout(layoutName).then(function(result){
padArea.getButtonId('A0')
});
奇怪的是,只要我将第二个调用包装在( .then 中的那个)中,我的原始代码也能正常工作。
只需使用$http
承诺:
factory.loadLayout = function (layoutName) {
return $http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
resolve('OK');
})
.error(function(data,status,headers,config){
reject(new Error( status));
});
}
然后使用它...
factory.loadLayout(param).then(function (response) { ... });
或
我明白你想做什么了。而是创建一个延迟的 $q
factory.loadLayout = function (layoutName) {
var defer = $q.defer();
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
defer.resolve('OK');
})
.error(function(data,status,headers,config){
defer.reject(new Error( status));
});
return defer.promise;
}
您也可以使用 $q.defer():
deferred = $q.defer();
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
deferred.resolve("OK");
})
.error(function (data,status,headers,config){
deferred.reject(new Error(status));
})
return deferred.promise;
如果您不只是执行 http 请求,这可能会更通用一些,并且让您控制 return。
我想我可能遗漏了一些关于 promise 如何运作的基本知识,因为我似乎从来没有得到我期望的结果,所以希望有人能纠正我的想法。
在这种情况下,这是一个相对容易的调用。我有一个 angular 工厂,除其他外,它从 API(调用 mongodb)获取一些数据。
由于有一个 $http 请求(异步),我将 http 调用包装在一个 $q 函数中,如果成功,该函数应该 return 一个 resolve
,如果一个错误则应该 reject
。
factory.loadLayout = function (layoutName) {
return $q(function(resolve, reject){
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
resolve('OK');
})
.error(function(data,status,headers,config){
reject(new Error( status));
});
});
}
然后我有另一个函数,它依赖于第一个函数中收集的数据,称为 getButtonId,但据我所知,即使它包含在 .then
中,它似乎它在承诺解决之前被调用。
var promise = padArea.loadLayout(layoutName);
promise.then(padArea.getButtonId('A0'));
那我错过了什么?
==更新== 所以使用 q.defer
尝试同样的事情factory.loadLayout = function (layoutName) {
var defer = $q.defer()
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
defer.resolve('OK');
})
.error(function(data,status,headers,config){
defer.reject(new Error( status));
});
return defer.promise;
}
仍然没有像我预期的那样工作,.then 中的函数仍然在 http 完成之前被调用。
== 更新 2 == 好的,它开始工作了(如果我只是在 .then 中调用工厂中的函数,它会直接调用它,但是,如果我将它包装在下面的函数中,它会突然起作用。谁能解释为什么,因为对我来说,将对函数的调用包装在函数内与仅调用函数没有区别。
padArea.loadLayout(layoutName).then(function(result){
padArea.getButtonId('A0')
});
奇怪的是,只要我将第二个调用包装在( .then 中的那个)中,我的原始代码也能正常工作。
只需使用$http
承诺:
factory.loadLayout = function (layoutName) {
return $http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
resolve('OK');
})
.error(function(data,status,headers,config){
reject(new Error( status));
});
}
然后使用它...
factory.loadLayout(param).then(function (response) { ... });
或
我明白你想做什么了。而是创建一个延迟的 $q
factory.loadLayout = function (layoutName) {
var defer = $q.defer();
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
defer.resolve('OK');
})
.error(function(data,status,headers,config){
defer.reject(new Error( status));
});
return defer.promise;
}
您也可以使用 $q.defer():
deferred = $q.defer();
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
deferred.resolve("OK");
})
.error(function (data,status,headers,config){
deferred.reject(new Error(status));
})
return deferred.promise;
如果您不只是执行 http 请求,这可能会更通用一些,并且让您控制 return。