【问题标题】:Promise, await/async and Promise.all: When all this is resolved?Promise、await/async 和 Promise.all:这一切什么时候解决?
【发布时间】:2020-09-03 12:20:54
【问题描述】:

我正在编写一个连接到 API 的节点代码以获取一些数据。我使用 JS Promise 调用 API 并获取解析部分的数据。现在我需要调用不同的端点来获取完整的数据。所以我最终选择了 Promise.all。但我不能让它工作。我读到异步函数也返回一个 Promise。所以也许我的代码没有正确处理 async/Promise 方法。

我用我拥有的类似代码做了一个代码笔。我无法获得要写入的最后一个日志。这个日志是在 Promise.all 解决的时候写的...

const getEntitiesData = async function () {
  await getEntities().then(function (response) {
    console.log("All entities: " + response.join(", "));
    const entitiesData = response.map(function (entity) {
      getEntityData(entity).then(function (response) {
        console.log("Entity data: " + JSON.stringify(response));
      });
    });
    return entitiesData;
  });
};

const getEntities = function () {
  return new Promise((resolve, reject) => {
    console.log("Getting all entities");
    setTimeout(resolve, 3000, [1, 2, 3, 4]);
  });
};
const getEntityData = function (id) {
  return new Promise((resolve, reject) => {
    console.log(`Getting entity ${id} data`);
    setTimeout(resolve, id*1000, { id: id, ref: "!"+id });
  });
};

const data = getEntitiesData();
Promise.all(data).then(function (response) {
  console.log("All Data get: " + response);
});

感谢您的帮助。我错过了什么?

【问题讨论】:

  • 您是否尝试在单个 Promise 上使用 Promise.all? getEntitiesData() 没有返回任何东西,你需要在 await 上返回
  • 您需要在此处在您的问题中发布minimal reproducible example,并在任何第三方网站上发布not a link
  • 请将与您的问题相关的代码放在您的问题中,粘贴为文本并适当格式化。这使您的问题可搜索,它对移动用户更有效,将来不会改变,因为外部链接有消失或改变的习惯,这是这里的规则。
  • 这里有很多问题。第一个问题是response.map() 回调需要返回它的承诺,而该回调中的.then() 处理程序需要返回它的值。
  • .map() 根据您从 .map() 回调返回的内容返回一个新数组。在 cmets 中阅读多行代码有点困难,但我认为您已经进行了我在那里建议的两个更改。

标签: javascript node.js promise async-await axios


【解决方案1】:

您的异步函数中缺少返回。 此外,当您拨打getEntitiesData 时,您不会在等待它。所以,它给了你一个承诺列表的承诺。当您等待时,您会获得内部的承诺列表,您可以对其执行Promise.all()

以下代码适用于此。

你想在这方面做得更好吗?看看你是否可以完全避免.then()。当你混合等待时,它变得非常混乱。

const getEntitiesData = async function () {
  return await getEntities().then(function (response) {
    console.log("All entities: " + response.join(", "));
    const entitiesData = response.map(function (entity) {
      return getEntityData(entity).then(function (response) {
        console.log("Entity data: " + JSON.stringify(response));
        return JSON.stringify(response);
      });
    });
    return entitiesData;
  });
};

const getEntities = function () {
  return new Promise((resolve, reject) => {
    console.log("Getting all entities");
    setTimeout(resolve, 3000, [1, 2, 3, 4]);
  });
};
const getEntityData = function (id) {
  return new Promise((resolve, reject) => {
    console.log(`Getting entity ${id} data`);
    setTimeout(resolve, id*1000, { id: id, ref: "!"+id });
  });
};

const main = async () => {
  const data = await getEntitiesData();
  Promise.all(data).then(function (response) {
    console.log("All Data get: " + response);
  });
}

main();

所以,这里是 no-then() 版本:

const getEntitiesData = async function () {
  let response = await getEntities();
  const entitiesData = response.map(async function (entity) {
    let response = await getEntityData(entity);
    console.log("Entity data: " + JSON.stringify(response));
    return JSON.stringify(response);
  });
  
  return entitiesData;
};

const getEntities = function () {
  return new Promise((resolve, reject) => {
    console.log("Getting all entities");
    setTimeout(resolve, 3000, [1, 2, 3, 4]);
  });
};
const getEntityData = function (id) {
  return new Promise((resolve, reject) => {
    console.log(`Getting entity ${id} data`);
    setTimeout(resolve, id*1000, { id: id, ref: "!"+id });
  });
};

const main = async () => {
  const data = await getEntitiesData();
  const response = await Promise.all(data);
  console.log("All Data get: " + response);
}

main();

但是返回一个承诺列表的承诺没有多大意义。我更喜欢这个:

所以,这是结构更好的 no-then() 版本:

const getEntitiesData = async function () {
  let response = await getEntities();
  const entitiesData = response.map(async function (entity) {
    let response = await getEntityData(entity);
    console.log("Entity data: " + JSON.stringify(response));
    return JSON.stringify(response);
  });
  
  return Promise.all(entitiesData);
};

const getEntities = function () {
  return new Promise((resolve, reject) => {
    console.log("Getting all entities");
    setTimeout(resolve, 3000, [1, 2, 3, 4]);
  });
};
const getEntityData = function (id) {
  return new Promise((resolve, reject) => {
    console.log(`Getting entity ${id} data`);
    setTimeout(resolve, id*1000, { id: id, ref: "!"+id });
  });
};

const main = async () => {
  const response = await getEntitiesData();
  console.log("All Data get: " + response);
}

main();

【讨论】:

  • 我喜欢你的例子。你只是像我一样忘记在 getEntityData(entity) 的解析中返回响应
  • 谢谢,你是对的。我在第一个函数中也忽略了一个。我刚刚编辑了它,现在应该可以按预期打印最后一行了。
【解决方案2】:

您只是没有在所有 then 回调中返回值。我刚刚在每个 then 回调函数中添加了返回值。

使用异步/等待:

const getEntitiesData = async function() {
  const responses = await getEntities();
  console.log("All entities: " + responses.join(", "));

  const entitiesData = responses.map(async function(entity) {
    const response = await getEntityData(entity);
    console.log("Entity data: " + JSON.stringify(response));

    return response;
  });

  return Promise.all(entitiesData);
};

const getEntities = function() {
  return new Promise((resolve, reject) => {
    console.log("Getting all entities");
    setTimeout(resolve, 3000, [1, 2, 3, 4]);
  });
};
const getEntityData = function(id) {
  return new Promise((resolve, reject) => {
    console.log(`Getting entity ${id} data`);
    setTimeout(resolve, id * 1000, {
      id: id,
      ref: "!" + id
    });
  });
};

const data = getEntitiesData();
data.then(function(response) {
  console.log("All Data get: " + JSON.stringify(response));
});

const getEntitiesData = function () {
  return getEntities().then(function (response) {
    console.log("All entities: " + response.join(", "));
    const entitiesData = response.map(function (entity) {
      return getEntityData(entity).then(function (response) {
        console.log("Entity data: " + JSON.stringify(response));
        return response;
      });
    });
    return entitiesData;
  }).then(p=>Promise.all(p));
};

const getEntities = function () {
  return new Promise((resolve, reject) => {
    console.log("Getting all entities");
    setTimeout(resolve, 3000, [1, 2, 3, 4]);
  });
};
const getEntityData = function (id) {
  return new Promise((resolve, reject) => {
    console.log(`Getting entity ${id} data`);
    setTimeout(resolve, id*1000, { id: id, ref: "!"+id });
  });
};

const data = getEntitiesData();
data.then(function (response) {
  console.log("All Data get: " + JSON.stringify(response));
});

【讨论】:

  • 嗨@user120242!感谢您的回答。我想知道.then(p=>Promise.all(p)) 是如何工作的... then 是否总是因为承诺而被解雇?我不明白这如何返回一个 Promise 数组。它工作得很好,但我可以看到它是如何工作的。我看到它将返回一个只有第一个 Promise (p) 的 Promise.all ...
  • entitiesData 是一个 Promise 数组,因此它最终是一个发出 Promise 数组的 Promise。我在 p 中捕获了 Promise 数组,然后返回 Promise.all,所以我得到了最终的 Promise,它在最后解析为一个值数组。
【解决方案3】:
function getEntities() {
    return new Promise((resolve, reject) => {
    console.log("Getting all entities");
    setTimeout(resolve, 3000, [1, 2, 3, 4]);
  });
}

function getEntityData(id) {
  return new Promise((resolve, reject) => {
    console.log(`Getting entity ${id} data`);
    setTimeout(resolve, id*1000, { id: id, ref: "!"+id });
  });
};

async function getEntitiesData() {
   const entities = await getEntities();
   const entitiesData = entities && entities.map(entity => await getEntityData())
}

const data = await getEntitiesData.map(response => console.log("All Data get: " + response);

你好 MuyBien,我试着清理一下代码。上面代码中缺少的部分是await in getEntityData(entity).then(function (response) {return

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-18
    • 2018-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多