【问题标题】:angular chaining arrays of promisesPromise 的角度链接数组
【发布时间】:2017-03-09 12:21:06
【问题描述】:

我正在建立一个基于音乐曲目数据库的网站。数据库如下:

  • music 表包含 musicid 和标题
  • musicrights 表包含 musicidmemberid
  • members 表包含 memberid 和 memberinfo。

我正在尝试在我的database 服务中构建一个对象数组,其中每个条目代表一个包含其权利持有者(包含关于一个权利持有者的信息但不包含其姓名的信息)及其成员信息(包含名称等)的轨道。后端是sailsjs,代码如下:

angular.module("myapp").service("database", ["$q", "$http", function($q, $http) {

  var database = {};

  function getHolderMember(rightHolder) {
    return ($http.get("/api/members?where=" + JSON.stringify({
      memberid: rightHolder.memberid
    })).then(function (res) {
        rightHolder.member = res.data[0];
        return (rightHolder);
    }));
  }

  function getRightHolders(doc) {
    return ($http.get("/api/musicrights?where=" + JSON.stringify({
      musicid: doc.musicid
    })).then(function(res) {
      // array of promises :
      // each rightholder of a document has to solve member info
      var rightHolders = [];
      for (var i in res.data) {
        var rightHolder = {
          member: res.data[i].memberid,
          type: res.data[i].membertype,
          rights: res.data[i].memberrights
        };
        rightHolders.push(getHolderMember(rightHolder));
      }
      return ($q.all(rightHolders));
    }).then(function(rightHolders) {
      // expected array of one or two rightholders,
      // enriched with member information

      // actually returns array of one or two arrays of 30 members
      // without rightholder info
      console.log(rightHolders);
      doc.rightHolders = rightHolders;
      return (doc);
    }));
  }

  database.music = function(q) {
    return ($http.get("/api/music?where=" + JSON.stringify({
      or: [{
        title: {
          contains: q
        }
      }, {
        subtitle: {
          contains: q
        }
      }]
    })).then(function(res) {
      // array of 30 promises :
      // each one of 30 documents has to resolve its rightholders
      var documents = [];
      for (var i in res.data) {
        documents.push(getRightHolders(res.data[i]));
      }
      return ($q.all(documents));
    }));
  }

  return (database);
}]);

第一个 promise 数组似乎按预期工作,但 getRightHolders 中的第二个不是。奇怪的是,这个函数返回了一个包含一两个promise的数组,它们是rightHolders在等待他们的memberinfo。但是在我 console.log 响应的回调中,我得到一个或两个数组(根据推送的承诺的数量),但这个数组的元素是 30 个成员信息的数组,而不是一个成员信息。我不明白这个 $q.all() 调用是如何与上一级 $q.all 混合的。

数据结构大致是这样的

  • 文档 [ ]($http => 30 个响应)
    • music.musicid
    • music.rightHolders [ ]($http => 1、2、3 响应)
      • rightholder.rights
      • rightholder.member ($http => 1 响应)
        • member.memberinfo

任何帮助表示赞赏。谢谢!

更新:感谢您的回答,它就像一个魅力。这是更新的代码,还有以不同方式格式化数据的迁移服务(正在进行一些数据库迁移)。我将它排除在第一个示例之外,但您的回答给了我这种简洁的语法。

angular.module("myApp").service("database", ["$q", "$http", "migrate", function($q, $http, migrate) {

        var database = {};

        function getHolderMember(rightHolder) {
          return ($http.get("/api/members?where=" + JSON.stringify({
            memberID: rightHolder.member
          })).then(function(res) {
            return (migrate.member(res.data[0]));
          }).then(function(member) {
            rightHolder.member = member;
            return (rightHolder);
          }));
        }

        function getRightHolders(doc) {
          return ($http.get("/api/rightHolders?where=" + JSON.stringify({
            musicID: doc.musicID
          })).then(function(res) {
            return (
              $q.all(res.data
                .map(migrate.rightHolder)
                .map(getHolderMember)
              )
            );
          }).then(function(rightHolders) {
            doc.rightHolders = rightHolders;
            return (doc);
          }));
        }

        database.music = function(q) {
          return ($http.get("/api/music?where=" + JSON.stringify({
            or: [{
                title: {
                  contains: q
                }
              },
              {
                subtitle: {
                  contains: q
                }
              }
            ]
          })).then(function(res) {
            return (
              $q.all(res.data
                .map(migrate.music)
                .map(getRightHolders)
              )
            );
          }));
        }

        return (database);
      }

【问题讨论】:

  • getRightsHolders函数中var rightHolder的作用是什么?看起来您正在创建它以将其传递给 getHolderMember,但随后 getHolderMember 仅使用其三个属性之一。
  • 是的,我曾经在$http 调用getHolderMember 之后有一个then,它将返回的成员存储在请求的RightHolder 中。这三个属性将在视图中使用,如documents[n].rightHolders[n].rightsdocuments[n].rightHolders[n].member.memberInfo。为了尝试使这项工作进行了很多修改,我想为了清楚起见,我应该将其放回示例中。

标签: angularjs arrays promise chaining


【解决方案1】:

我不太确定你是如何得到你描述的结果,但你的逻辑比它需要的更复杂,我认为这可能会导致你看到的问题。您赋予getRightsHolders 函数返回文档的责任,根据您上面的评论,听起来您之前让getHolderMember() 函数做了类似的事情,然后停止了。

我们可以通过让每个函数负责它正在处理的实体并使用.map() 而不是for 来清理这个问题(请不要将for..in 与数组一起使用)。

请试一试:

angular
  .module("myapp")
  .service("database", ["$q", "$http", function($q, $http) {
    var database = {};

    function getHolderMember(memberId) {
      var query = JSON.stringify({ memberid: memberid });
      return $http.get("/api/members?where=" + query)
          .then(function (res) {
              return res.data[0];
          });
    }

    function populateRightsHolderWithMember(rightsHolder) {
       return getHolderMember(rightsHolder.memberid)
         .then(function (member) {
           rightsHolder.member = member;
           return rightsHolder;
         });
    }

    function getRightHolders(doc) {
      var query = JSON.stringify({ musicid: doc.musicid });

      return $http.get("/api/musicrights?where=" + query)
        .then(function(res) {
          return $q.all(res.data.map(populateRightsHolderWithMember));
        });
    }

    function populateDocumentWithRightsHolders(document) {
      return getRightsHolders(document)
        .then(function(rightsHolders) {
          document.rightsHolders = rightsHolders;
          return document;
        });
    }

    database.music = function(q) {
      return $http.get("/api/music?where=" + JSON.stringify({
        or: [{
          title: {
            contains: q
          }
        }, {
          subtitle: {
            contains: q
          }
        }]
      })).then(function(res) {
        return $q.all(res.data.map(populateDocumentWithRightsHolders));
      });
    }

    return (database);
  }]);

【讨论】:

猜你喜欢
  • 2016-07-14
  • 2016-12-08
  • 1970-01-01
  • 2014-04-29
  • 1970-01-01
  • 2020-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多