我对角度很陌生,而且我被推进了一个相当大的项目。我的情况已经简化为以下代码:
var beforeClose = function() {
var closeDeferred = $q.defer(),
a = $q.defer(),
b = $q.defer(),
c = $q.defer(),
promiseArray = [a.promise, b.promise, c.promise];
/* logic that resolves or rejects a, b, and c */
$q.all(promiseArray).then(
function() {
closeDeferred.resolve();
},
function() {
closeDeferred.reject();
}
);
return closeDeferred.promise;
}
var modalClose = function() {
beforeClose().then(
function() {
//close the modal
},
function() {
//warn and don't close modal
}
)
}
使用Chrome的DevTools,似乎代码在完全解决或拒绝 closeDeferred
之前返回promiseArray
承诺。所以我想我的问题就像,
什么时候承诺退回?可以在解决或拒绝之前退回吗?如果没有,我怎么能阻止它返回?
将return语句放入函数(例如,在promiseArray
resolve和reject函数中)使该函数返回promise,但不一定将该promise发送给modalClose
(这解雇了第一个承诺)。
或许我理解我的代码会发生什么。当我将返回closeDeferred
放入另一个函数时,我发现错误,指出.then()
无法在未定义时调用(指向beforeClose().then()
})。
修改:在查看安德鲁的回答之后,我不得不更新代码,并且更具体地说明了发生了什么。
问题不一定是在我想要之前返回承诺,而是它正在为该承诺执行解析函数 - 它会关闭模态,即使promiseArray()
没有& #39; t完成它的事情。
编辑2:所以看来,在简化代码结构时,我实际上删除了我的真正问题。在承诺的各种设置中,事实证明我在返回语句之前从未实际将closeDeferred定义为延迟或承诺。因此,当循环机制完成了它应该做的事情时,它也会返回closeDeferred.promise,未定义,我猜?所以modalClose函数在任何promises被解析/拒绝之前运行。然后在下一个循环中,最终定义了closeDeferred,并且承诺正确地起作用。
尽管如此,我真的很感激所给予的帮助。 @ andrew-tomlinson和@georgeawg都让我对承诺有了更好的理解。它没有回答这个问题(因为我错误地定义了这个问题),但它肯定非常有用。谢谢!
答案 0 :(得分:5)
乍一看,您似乎正在使用Defer对象加载promiseArray。根据文档(在这里找到:https://docs.angularjs.org/api/ng/service/ $ q),似乎all()方法需要一个Promise对象数组。
要从Defer对象获取承诺,您可以将其作为属性访问:
var myDeferedObj = $q.defer();
var myPromiseObj = myDeferedObj.promise;
然后你将在promiseArray中使用promise对象。在您的示例中实现的这个想法会将其改为:
a = $q.defer().promise,
b = $q.defer().promise,
c = $q.defer().promise,
promiseArray = [a,b,c];
注意,我没有亲自测试过,但是如果你仍然被卡住,你可以尝试一下。祝你好运!
编辑:在更彻底地阅读了一些问题之后,我觉得我需要改变我的回答以解决一些具体问题。如果您已经知道这一点,我很抱歉,我错过了问题的重点。
"承诺何时返回?"
执行return
方法时,从函数返回Promise对象。返回promise对象在概念上与解析或拒绝promise无关。返回Promise对象通常是为了在应用程序中传递Promise的引用。在您的示例中,您将Promise对象从beforeClose()
函数传递给modalClose()
函数。在承诺被解决或拒绝之前,.then(function(){},function(){})
内的Promise对象(使用modalClose()
)上提供的回调函数将不会执行。
"可以在解决或拒绝之前退回吗?"
是的,Promise对象closeDeferred.promise
将立即从beforeClose()
返回,但是根据我对示例代码的理解,在promiseArray中的promise被解决或拒绝之前,不应该解析或拒绝它统称。也就是说,return closeDeferred.promise;
不是阻塞语句,并且将像函数末尾的任何正常return语句一样执行。
有一个非常简单的(非常简单的)Promise概念的例证here被解释为卡通片。
答案 1 :(得分:2)
返回 #!/bin/sh
# unix time in s that we should wake at
waketime=$(date +%s -d '08:00')
# make sure the time we got is in the future
if [ $(date +%s) -gt $waketime ]; then
# if not add a day 60s * 60s * 24h
waketime=$(($waketime + 86400))
fi
# time in S from now till then
dif=$(($waketime - $(date +%s)))
# tell the user
echo
echo "Current Time : $(date +%s)"
echo "Wake Time : $waketime"
echo "Seconds From Now : $dif"
echo
echo "Crtl-C to Cancel in 5s"
echo
sleep 5
# sleep with rtcwake
/usr/sbin/rtcwake -m off -l -s $dif
echo "Shutdown."
承诺。
$q.all
请注意var beforeClose = function() {
//var closeDeferred = $q.defer(),
var a = $q.defer(),
var b = $q.defer(),
var c = $q.defer(),
var promiseArray = [a.promise, b.promise, c.promise];
/* logic that resolves or rejects a, b, and c */
var pAll = $q.all(promiseArray).then(
function(resultsList) {
resultsA = resultsList[0];
resultsB = resultsList[1];
resultsC = resultsList[2];
return something;
},
function(error) {
throw error;
}
);
return pAll;
}
不具弹性。如果任何promises抛出错误,它将解决(被拒绝)第一个错误。
$q.all
功能会立即返回承诺。承诺将在将来中的某些时间解决(包含数据或错误)。 $q.all
服务延迟了$q
方法中函数的执行,直到promise用数据解析;在.then
方法中有错误。
.catch
答案 2 :(得分:0)
我可能会误读这一点,但您似乎应该发送$q.all
个承诺对象并使用承诺的内置.catch
功能:
var beforeClose = function() {
var closeDeferred = $q.defer(),
a = $q.defer().promise, // send promise objects to promiseArray
b = $q.defer().promise, // send promise objects to promiseArray
c = $q.defer().promise, // send promise objects to promiseArray
promiseArray = [a,b,c];
/* logic that resolves or rejects a, b, and c */
$q.all(promiseArray)
.then(closeDeferred.resolve();)
.catch(closeDeferred.reject();)
return closeDeferred.promise;
}
var modalClose = function() {
beforeClose()
.then( //close the modal )
.catch( //warn and don't close modal );
}