简体   繁体   中英

Promise, await/async and Promise.all: When all this is resolved?

I'm writing a node code that connect to an API in order to get some data. I use JS Promise to call the API and get the data on the resolve part. Now I need to call different endpoints to get a complete data. So I ended up with Promise.all. But I can't make it work. I read that the async function return a Promise as well. So maybe my code is not handling properly the async/Promise methods.

I did a codepen with a similar code I have. I cannot get the last log to be written. This log is written when the Promise.all is resolved...

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

Thanks for any help. What am I missing?

You are missing returns in your async functions. Also, when you call getEntitiesData , you are not awaiting it. So, it gives you a promise of list of promises. When you await, you get the inner list of promises, to which you can do Promise.all() .

Below code works in this light.

Do you want to get better at this? See if you can avoid .then() altogether. When you mix await and then, it becomes really confusing.

 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();

So, here's the no-then() version:

 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();

but it does not make a lot of sense to return a promise of list of promises. I like this better:

So, here's the no-then() version with a better structure:

 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();

You just aren't returning values in all of your then callbacks. I've just added returns in every then callback function.

Using async/await:

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

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

Hello MuyBien, I tried to clean the code a bit. And the part you're missing in the above code is await in getEntityData(entity).then(function (response) { and return too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM