我正在尝试将返回的ID列表过滤/匹配到JSON数据记录列表,但我正在努力(我相信)我的承诺和方法链接。
除了添加下面的步骤3之外,我可以使函数正常工作。然后它会在没有匹配数据的情况下解析(函数会继续执行并最终返回正确的匹配数据,但到那时我的方法已经完成)。
它应该如何运作:
这是我的主要方法:
this.getCompanyBrandProfileIDs = function () {
var brandProfileIDsToReturn = $q.defer();
GetUserAccessService.returnBrandProfileID().then(function (brandProfileID) {
console.log(brandProfileID);
getBrandProfiles(brandProfileID).then(function (brandProfiles) {
console.log(JSON.stringify(brandProfiles));
var keywordProfilesArray = [];
getKeywordProfiles(brandProfiles).then(function (keywordProfiles) {
keywordProfilesArray = keywordProfiles;
console.log(JSON.stringify(keywordProfilesArray));
//brandProfileIDsToReturn.resolve(keywordProfilesArray);
});
brandProfileIDsToReturn.resolve(keywordProfilesArray);
});
});
return brandProfileIDsToReturn.promise;
};
这是getBrandProfiles方法:
function getBrandProfiles(brandProfileID) {
var getBrandProfilesLinkedToCompany = $q.defer();
pullSocialMediaData('keyword_profile_brand_profiles.json?brand_profile_id=' + brandProfileID).then(function (brandProfiles) {
var brandProfilesArray = [];
brandProfiles.forEach(function (profile) {
brandProfilesArray.push({ id: profile.id, name: profile.name });
});
getBrandProfilesLinkedToCompany.resolve(brandProfilesArray);
});
return getBrandProfilesLinkedToCompany.promise;
}
这是getKeywordProfiles方法:
function getKeywordProfiles(brandProfiles) {
var keywordProfilesToReturn = $q.defer();
var brandProfilesArray = brandProfiles;
var array = [];
brandProfilesArray.forEach(function (profile) {
findKeywordProfile(profile.id).then(function (keywordID) {
array.push(keywordID);
});
keywordProfilesToReturn.resolve(array);
})
return keywordProfilesToReturn.promise;
}
这是getKeywordProfiles的辅助方法:
function findKeywordProfile(brandProfileID) {
var keywordProfileID = $q.defer();
pullSocialMediaData('list_keyword_profiles.json').then(function (data) {
var keywordProfileInstance = data.filter(function (keyword) {
return keyword.brand_profile_id === brandProfileID;
});
keywordProfileID.resolve(keywordProfileInstance[0].id);
});
return keywordProfileID.promise;
}
感谢您的协助!
答案 0 :(得分:1)
您即将解决brandProfileIDsToReturn
。在此代码中:当您解析承诺时,将不会调用then
回调,因此keywordProfilesArray
保证为空。
this.getCompanyBrandProfileIDs = function () {
var brandProfileIDsToReturn = $q.defer();
GetUserAccessService.returnBrandProfileID().then(function (brandProfileID) {
console.log(brandProfileID);
getBrandProfiles(brandProfileID).then(function (brandProfiles) {
console.log(JSON.stringify(brandProfiles));
var keywordProfilesArray = [];
getKeywordProfiles(brandProfiles).then(function (keywordProfiles) {
keywordProfilesArray = keywordProfiles;
console.log(JSON.stringify(keywordProfilesArray));
//brandProfileIDsToReturn.resolve(keywordProfilesArray);
});
brandProfileIDsToReturn.resolve(keywordProfilesArray);
});
});
return brandProfileIDsToReturn.promise;
};
只需移动resolve()
回调内的then
号即可修复它,实际上您已将该行注释掉,因此取消注释并删除其他解析:
this.getCompanyBrandProfileIDs = function () {
var brandProfileIDsToReturn = $q.defer();
GetUserAccessService.returnBrandProfileID().then(function (brandProfileID) {
console.log(brandProfileID);
getBrandProfiles(brandProfileID).then(function (brandProfiles) {
console.log(JSON.stringify(brandProfiles));
var keywordProfilesArray = [];
getKeywordProfiles(brandProfiles).then(function (keywordProfiles) {
keywordProfilesArray = keywordProfiles;
console.log(JSON.stringify(keywordProfilesArray));
brandProfileIDsToReturn.resolve(keywordProfilesArray);
});
});
});
return brandProfileIDsToReturn.promise;
};
但是,如果停止使用$q.defer()
,您可能会大量简化代码。你的函数已经返回promises,所以只需返回他们使用的promises并停止尝试创建额外的promise。我认为这相当于前面的代码,除了它直接返回promises,我删除了日志消息,这意味着getKeywordProfiles调用简化为只调用函数的回调,因此你可以直接传递函数:
this.getCompanyBrandProfileIDs = function () {
return GetUserAccessService.returnBrandProfileID().then(function (brandProfileID) {
return getBrandProfiles(brandProfileID).then(getKeywordProfiles);
});
});
};
然后您可以通过提取内部.then
:
this.getCompanyBrandProfileIDs = function () {
return GetUserAccessService.returnBrandProfileID()
.then(getBrandProfiles)
.then(getKeywordProfiles);
};
getKeywordProfiles()
函数还需要避免解决其承诺,直到所有findKeywordProfile()
调用都已解决。返回承诺数组的承诺,当他们解决承诺时,将完成一系列值:
function getKeywordProfiles(brandProfilesArray) {
var array = [];
brandProfilesArray.forEach(function (profile) {
array.push(findKeywordProfile(profile.id));
})
return $q.all(array);
}
为了澄清我对$q
的评论,在某些情况下您需要使用它从头开始创建承诺,但它们相当不常见。在Angular中异步发生的任何事情都会返回一个承诺,而承诺的好处是它们链接在一起,所以当你有一个承诺,调用.then()
或.catch()
将返回一个新承诺。此外,.then()
回调可以返回一个解析新promise的值,也可以返回一个promise,它只会在它自身解析时解析新的promise。因此,只需将.then()
个调用链接在一起,每个调用都将等待前一个调用完成。
$q
仍然有用:$q.all()
如果你想要等待所有解决方案的一堆承诺,$q.race()
如果你有一堆承诺,只有一个需要解决,$q.resolve(value)
也很有用,因为有时你只想要一个会立即解决的承诺,这样你就可以挂掉一连串其他异步函数。
在解决之后很长时间保持承诺是安全的,你仍然可以在其上调用.then()
:如果你有异步初始化代码和事件可能会或可能不会被触发,这是很有用的初始化已经完成。当你可以if(isInitialised)
initPromise.then(...)
答案 1 :(得分:1)
在getKeywordProfiles
函数中,您需要在数组循环完成时解决它。
function getKeywordProfiles(brandProfiles) {
var keywordProfilesToReturn = $q.defer();
var brandProfilesArray = brandProfiles;
var array = [];
brandProfilesArray.forEach(function (profile) {
findKeywordProfile(profile.id).then(function (keywordID) {
array.push(keywordID);
});
//--
//keywordProfilesToReturn.resolve(array);
})
//++
keywordProfilesToReturn.resolve(array);
return keywordProfilesToReturn.promise;
}
信息:我认为你需要创建一个profileIdArray来推送所有brandProfileID并发送到你的findKeywordProfile函数。它会更有用。