Promise在Array.map之前返回。为什么?

时间:2019-06-19 18:40:17

标签: node.js es6-promise

我的代码中有两个功能;一种是获取保姆的名字,另一种是获取每个保姆的孩子的名字。

我输入的代码是一个模型,因为在现实世界中,我将其绑定到一个接受Sitter ID作为变量并返回具有Sitter ID的Children数据集的数据库。从本质上讲,它们是针对Sitter的1个数据库查询和每个Sitter的1个数据库查询。

目标是遍历Sitters并调用一个传递Sitter ID的函数,该ID将使我获得孩子身份。

我想将子级添加到迭代的Sitter中。

我的问题是,一旦获得了Sitter,程序就会终止,而每个Sitter都没有孩子。

我认为在Sitters上使用.map会使代码等待拉出子级的代码,但它会立即解决。

我尝试了各种Async / Await和Promise组合,但无法迭代Sitters,轮询每个Sitter的子代,然后返回填充了Children的Sitters变量。

const getSitters = () => {

    return new Promise((resolve) => {

        const sitters = [{

            id: 1,

            displayName: 'Sitter 1'

        }, {

            id: 2,

            displayName: 'Sitter 2'

        }];

        resolve({

            result: 'ok',

            sitters: sitters

        });

    });

};

const getChildrenBySitter = (getChildrenBySitterRequest) => {

    return new Promise((resolve) => {

        const children = [{

            id: 1,

            displayName: `Child 1 for Sitter ${getChildrenBySitterRequest.sitterId}`

        }, {

            id: 2,

            displayName: `Child 2 for Sitter ${getChildrenBySitterRequest.sitterId}`

        }];

        resolve({

            result: 'ok',

            children: children

        });

    });

};

getSitters().then((getSittersResponse) => {

    return getSittersResponse;

}).catch((getSittersResponse) => {

    return getSittersResponse;

}).then((getSittersResponse) => {

    const sitters = getSittersResponse.sitters;

    sitters.map(sitter => {

        const getChildrenBySitterRequest = {

            sitterId: sitter.id

        };

        getChildrenBySitter(getChildrenBySitterRequest).then((getChildrenBySitterResponse) => {

            return getChildrenBySitterResponse;

        }).catch((getChildrenBySitterResponse) => {

            return getChildrenBySitterResponse;

        }).then((getChildrenBySitterResponse) => {

            const children = getChildrenBySitterResponse.children;

            sitter.children = children;

        });

    });

    console.log(JSON.stringify(sitters));

});

我希望对Sitters对象进行迭代,并为每个Sitter填充子代。

如您所见,它返回Sitter对象,然后再用Children填充它,然后代码完成了:(

1 个答案:

答案 0 :(得分:1)

您必须在地图函数中返回链接的诺言(1),等待每个诺言得到兑现(2),然后记录保姆(3):

getSitters()
  .then(getSittersResponse => {
    return getSittersResponse;
  })
  .catch(getSittersResponse => {
    return getSittersResponse;
  })
  .then(getSittersResponse => {
    const sitters = getSittersResponse.sitters;

    Promise.all( // 2
      sitters.map(sitter => {
        const getChildrenBySitterRequest = {
          sitterId: sitter.id,
        };

        return getChildrenBySitter(getChildrenBySitterRequest) // 1
          .then(getChildrenBySitterResponse => {
            return getChildrenBySitterResponse;
          })
          .catch(getChildrenBySitterResponse => {
            return getChildrenBySitterResponse;
          })
          .then(getChildrenBySitterResponse => {
            const children = getChildrenBySitterResponse.children;

            sitter.children = children;
          });
      }),
    ).then(_ => {
      console.log(JSON.stringify(sitters)); // 3
    });
  });

输出:

[{"id":1,"displayName":"Sitter 1","children":[{"id":1,"displayName":"Child 1 for Sitter 1"},{"id":2,"displayName":"Child 2 for Sitter 1"}]},{"id":2,"displayName":"Sitter 2","children":[{"id":1,"displayName":"Child 1 for Sitter 2"},{"id":2,"displayName":"Child 2 for Sitter 2"}]}]

您还可以使用async和await:

const main = async () => {
  let sittersResponse;

  try {
    sittersResponse = await getSitters();
  } catch (ex) {
    console.error(ex);
    return;
  }

  const {sitters} = sittersResponse;

  for (let i = 0; i < sitters.length; i += 1) {
    const sitter = sitters[i];

    let response;

    try {
      response = await getChildrenBySitter({
        sitterId: sitter.id,
      });
    } catch (ex) {
      console.error(ex);
      return;
    }

    sitter.children = response.children;
  }

  console.log(JSON.stringify(sitters));
};

main();