Angularjs 用一个带“的对象解决承诺”;然后";功能
这是一个有点抽象的问题,因为我现在没有特定的用例。我注意到如果你用承诺来解决承诺Angularjs 用一个带“的对象解决承诺”;然后";功能,angularjs,promise,Angularjs,Promise,这是一个有点抽象的问题,因为我现在没有特定的用例。我注意到如果你用承诺来解决承诺 var deferredA = $q.defer(); var deferredB = $q.defer(); deferredA.promise.then(function(result) { // Will get here once promiseB has been resolved. }); deferredA.resolve(deferredB.promise); 在允诺人被解决之前,允诺人实际上
var deferredA = $q.defer();
var deferredB = $q.defer();
deferredA.promise.then(function(result) {
// Will get here once promiseB has been resolved.
});
deferredA.resolve(deferredB.promise);
在允诺人被解决之前,允诺人实际上是不会被解决的(然后允诺人以允诺人的决议的价值被解决)。但是,如果我想用带有“then”函数的对象的值来解析,如:
var deferred = $q.defer();
deferred.promise.then(function(result) {
// Aim is to get here with result = {then:function(){}},
// as though I had resolved a promise with a non-promise value,
// but this function is never called
});
deferred.resolve({
then: function() {
}
});
然后promiseA实际上从未得到解决,因为它假设该值是一个承诺,即使在上面的示例中它不是,例如,它不是用$q.defer()创建的。有一个例子是plunkr
有办法解决这个问题吗?如果是,怎么做
编辑:澄清延迟/承诺并加入示例“然后”回调。解决方案
您传递的then
属性正在覆盖承诺的then
属性。相反,您希望从函数的成功回调中返回对象,然后如下所示:
$scope.resolvePromise2 = function() {
deferred2.resolve({
then: function(successCB) {
successCB({myResult1:'result1',
myResult2:'result2',
'then':function() {console.log("got here")}});
}
});
};
使用上面的命令,您的消息现在被调用,您可以在您的属性中调用then
函数:
promise2.then(function(result) {
//Now we get here
$scope.messages2.push('Promise 2 then callback. Result is:' + result);
result.then();
});
这是你的最新消息
问题/原因让我们看看角度:
你说过{then:function(){…}}不是承诺。好吧,根据A+规范的承诺
该规范规定承诺应该是可互操作的,也就是说,如果一个承诺是用一个thenable对象解析的,或者如果一个承诺的onfully回调返回一个thenable。一旦onFulfill返回的承诺或作为参数传递给resolve方法的承诺得到解决,第一个承诺的then方法返回的承诺就会得到解决
因此,您的承诺永远不会解决,因为您的thenable对象永远不会得到“解决”,也永远不会调用其onfully回调
这有点令人困惑,但让我们看看练习
var deferred = $q.defer();
deferred.promise.then(function(result) {
// A promise should not be resolved with another
});
deferred.resolve({
then: function() {
}
});
延迟的解决方法将看到你的对象的方法,并认为:“嗯,一个姐妹的承诺,我会得到解决,一旦它得到第一”。
因此,它将使用回调调用您的then函数,以实际解决您的承诺
这样:
yourThenable.then(function(spectedData){
// Your promise will resolve as soon as this callback gets called
// But your then function doesnt call the onFulfill callback
// Thats why it never resolves
}, function(spectedData){
// Also if this second parameter gets called your promise will be rejected
});
我不知道你为什么要这样做,但你不应该用一张表格来解决一个承诺。
你可以用另一种方式来完成你想要的
以下是我能想到的最简单的方法:
deferred.resolve([{
then: function() {
}
}]);
resolve方法将查找then方法,但现在您的对象不是thenable,该数组的0索引为
deferred.promise.then(function(result) {
// Now you have a result that is a Array
// And the index 0 is your thenable object
});
但是,在继续这样做之前,你真的应该三思而后行。我得出结论,这是不可能的。
只有将对象包装到另一个对象中而不包含属性,才能确保没有then
属性:
var deferred = $q.defer();
deferred.promise.then(function(result) {
// Aim is to get here with result = {then:function(){}},
// as though I had resolved a promise with a non-promise value,
// but this function is never called
result.result.then
});
deferred.resolve({ result: {
then: function() {}
}});
在调用resolve之前从对象中删除then函数,然后重新添加?目的是能够使用包含“then”函数的对象解析承诺。想要使用承诺解析值的函数可能与生成+解析承诺的函数位于完全不同的代码部分,因此我认为这是不可能的。有趣的是,它没有检测到$q.defer().promise
的实例。也许这是一个bug…这最终得到的是解析值“result”,而不是“then”successCallback中的对象{then:function(){},我想知道这是可能的。也许一个更现实的例子是,如果值中有其他一些数据/函数,比如{myResult1:'result1',myResult2:'result2',然后:function(){}:我在寻找回调中可用的myResult1,myResult2,然后所有数据/函数。您是否希望包含然后
,以获得不同的承诺?或者你认为这是递归的?如果resolve()调用的then
包含另一个then
函数,则递归的终止条件是什么?如果没有递归,我想这些都不是。有一些异步操作生成一个对象,该对象包含一个然后键,该键的值是一个函数。根据我之前的评论,对象中可能还有其他键。目的是将此对象用作承诺的完全解决价值。您可以使用{'myResult1':'result1','myResult2':'result2'}
作为解析值,但是如果您想将然后
作为函数包含{'myResult1':'result1','myResult2':'result2','then':function(){}
,那么这将停止解析承诺,正如最初的解释一样。谢谢-这很有帮助。我更新了答案(和plunker),并希望改进解释。解释起来有点棘手,因为你的then
属性和角度then
属性都在相互作用。我看到了:它做了我想要的。谢谢
deferred.promise.then(function(result) {
// Now you have a result that is a Array
// And the index 0 is your thenable object
});
var deferred = $q.defer();
deferred.promise.then(function(result) {
// Aim is to get here with result = {then:function(){}},
// as though I had resolved a promise with a non-promise value,
// but this function is never called
result.result.then
});
deferred.resolve({ result: {
then: function() {}
}});