如何在GraphQL解析器中使用多个API调用来构造承诺数组,以返回单个对象类型列表

时间:2018-09-20 19:23:44

标签: javascript promise graphql

我被困在GraphQL解析程序中,该程序为公司的特定用户获取待办事项列表。根据他们是否有权访问所有待办事项列表或少数几个待办事项列表,它将为注册的用户拥有属于待办事项列表的组取回文件,并应将其取回。

到目前为止,该代码能够在查询中记录请求的待办事项列表,但我还没有找到有关如何实际返回所有用户注册组的待办事项列表数据的解决方案。

我选择将实际逻辑导出到单独的函数中

解析器:

allowedListItems: {
  type: new GraphQLList(TodoItem),
  resolve(parentValue, args) {
    return Promise.all([fetchAllowedItems(parentValue._id)]);
  }
},

承诺功能

function fetchAllowedItems(userId) {
  return User.findOne({ _id: userId }).then((user) => {
    if (user.todoGroups) {
      return user.todoGroups.map((groupId) => {
        return TodoGroup.findOne({ _id: groupId }).then(group => {
          return group.todoLists.map((listId) => {
            return TodoList.findOne({ _id: listId })
          })
        })
      })
    } else {
      return TodoList.find({ company: parentValue.company }).exec();
    }
  })
}

我没有从GraphQL中得到任何错误,所以我想这与我让答辩者返回解析器有关,我非常感谢您能为我提供帮助!

更新:

我应该用Promise.all包装地图,因为映射返回一个数组。 尽管更新的代码对返回的数据没有任何改善。

async resolve(parentValue, args) {
    let user = await User.findOne({ _id: parentValue._id })

    if (user.todoGroups) {
      return Promise.all(user.todoGroups.map((groupId) => {
        return TodoGroup.findOne({ _id: groupId }).then(group => {
          return Promise.all(group.todoLists.map((listId) => {
            return TodoList.findOne({ _id: listId });
          }))
        })
      }))
    } else {
      return TodoList.find({ company: parentValue.company }).exec();
    }
  }
},

当前查询结果:

{
  "data": {
    "user": {
      "_id": "5ba11690ad7a93d2b34d21a9",
      "allowedTodos": [
        {
          "_id": null,
          "title": null
        }
      ]
    }
  }
}

1 个答案:

答案 0 :(得分:0)

您需要在一组承诺(而不是一个承诺)上调用Promise.all。另外,您还必须在每个级别上调用它​​:

allowedListItems: {
  type: new GraphQLList(TodoItem),
  resolve(parentValue, args) {
    return User.findOne({ _id: parentValue._id }).then(user => {
      if (user.todoGroups) {
        return Promise.all(user.todoGroups.map(groupId => {
//             ^^^^^^^^^^^^
          return TodoGroup.findOne({ _id: groupId }).then(group => {
            return Promise.all(group.todoLists.map(listId => {
//                 ^^^^^^^^^^^^
              return TodoList.findOne({ _id: listId })
            }));
          });
        }));
      } else {
        return TodoList.find({ company: parentValue.company }).exec();
      }
    });
  }
}