关于返回比较和更新的数组,Angular应用程序中的方法链接和承诺问题

时间:2017-02-27 12:29:19

标签: javascript angularjs angular-promise method-chaining

我正在尝试将返回的ID列表过滤/匹配到JSON数据记录列表,但我正在努力(我相信)我的承诺和方法链接。

除了添加下面的步骤3之外,我可以使函数正常工作。然后它会在没有匹配数据的情况下解析(函数会继续执行并最终返回正确的匹配数据,但到那时我的方法已经完成)。

它应该如何运作:

  1. (getCompanyBrandProfileIDs)首先,我的方法获取一个链接到当前用户的brandProfileID。
  2. (getBrandProfiles)然后它接受brandProfileID并获取链接到特定brandProfile的所有brandProfile。
  3. (getKeywordProfiles)然后<​​strong>应该获取返回的brandProfiles,并为每个brandProfile获取匹配的keywordProfile。它是一个包含brand_profile_id和id的对象数组。
  4. 这是我的主要方法:

    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;
    }
    

    感谢您的协助!

2 个答案:

答案 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函数。它会更有用。