0

I'm sure this is an issue with my understanding/implementation. The issue is that I'm trying to return the ID of the created object into an array so that array can later be inserted into another object. Moving the .then() between the function, the call, nothing seems to work. Pushing to the array, assigning the value to the array via index doesn't seem to work. Any insights/guidance into what the root issue is and a path to resolve it is appreciated.

index.js

const contacts = document.getElementsByName('newContact');
const contactName = document.getElementsByName('contactName');
const contactTitle = document.getElementsByName('contactTitle');
const contactPhone = document.getElementsByName('contactPhone');
const contactEmail = document.getElementsByName('contactEmail');
let contactIDArray = new Array();
for (let i = 0; i < contacts.length; i++) {
  const name = contactName[i].value;
  const title = contactTitle[i].value;
  const phone = contactPhone[i].value;
  const email = contactEmail[i].value;
  var id;
  createContact(name, title, phone, email).then(function (res) {
    id = res.data.id;
    alert(res.data.id);
    return id;
  });
  alert(id);

contact.js

import axios from 'axios';

export const createContact = async (contactName, contactTitle, contactPhone, contactEmail) => {
  try {
    const res = await axios({
      method: 'POST',
      url: '/api/v1/contacts',
      data: {
        contactName,
        contactTitle,
        contactPhone,
        contactEmail,
      },
    });
    return res.data.id;
  } catch (err) {
    console.log(err);
  }
};
  • 1
    `createContact` returns `res.data.id` and you then try to get `.data.id` from that *again*. – VLAZ Sep 24 '21 at 09:48
  • 1
    I'm not sure about what you are trying to achieve with the loop: the id will get reassigned in each callback call. Also, your callback is returning the id, but you're not using it afterwards – jkoestinger Sep 24 '21 at 09:52
  • Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Krzysztof Krzeszewski Sep 24 '21 at 09:53
  • @jkoestinger The loop will be responsible for creating one or many contact documents in the backend. Contacts belong inside of another structure called a tag. The array is to attach the IDs of each of the contact fields to the tag. I could store contacts inside the tag itself but that would break contact sharing functionality we have in store. – chrischelios_ Sep 24 '21 at 10:34
  • @KrzysztofKrzeszewski I'm looking into that now, thank you! – chrischelios_ Sep 24 '21 at 10:34

2 Answers2

0

There are multiple problems I can see:

  1. As VLAZ states in the comment, you're trying to get the .data.id on a value that is already an id
  2. Creating a sequence of promises should be done using the tools provided by the Promise util (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all might be what you are looking for).

For instance I would go with something along those lines (not tested):

const contacts = document.getElementsByName('newContact');
const contactName = document.getElementsByName('contactName');
const contactTitle = document.getElementsByName('contactTitle');
const contactPhone = document.getElementsByName('contactPhone');
const contactEmail = document.getElementsByName('contactEmail');
let contactIDArray = new Array();

const requests = []

for (let i = 0; i < contacts.length; i++) {
  const name = contactName[i].value;
  const title = contactTitle[i].value;
  const phone = contactPhone[i].value;
  const email = contactEmail[i].value;
  var id;
  promise = createContact(name, title, phone, email).then(function (res) {
    const id = res.data.id;
    alert(res.data.id);
    return id;
  });
  requests.push(promise)
} 

Promise.all(requests).then(ids => {
    // This should contain the array of ids
    alert(ids)
})

Edit: Also, be careful about sharing result between synchronous and asynchronous calls, usually you would stay in the async world once you started your async tasks, as stated here: How to return data from promise

jkoestinger
  • 980
  • 6
  • 8
0

I'm trying to return the ID of the created object into an array so that array can later be inserted into another object

Based on your request, I have a few things for you:

  1. Like jkoestinger's answer, do not use async/await or asynchronous functions (.then()) inside a loop unless you really need it.
  2. Do not return a property directly from the async call, you should return the whole object and get the ID. This is a good practice.

Please see the modified code below:

index.js

let contactPromises = [];

for (let i = 0; i < contacts.length; i++) {
  const name = contactName[i].value;
  const title = contactTitle[i].value;
  const phone = contactPhone[i].value;
  const email = contactEmail[i].value;
  
  contactPromises.push(createContact(name, title, phone, email));
}

let contacts = (contactPromises.length > 0) ? await Promise.all(contactPromises) : [];
let contactIds = contacts.map(contact => contact.id);
// use your contactIds here

axios

let res = await axios({
  method: 'POST',
  url: '/api/v1/contacts',
  data: {
    contactName,
    contactTitle,
    contactPhone,
    contactEmail,
  },
});

return res.data;   // <--- return res.data only, not the res.data.id
BraveVN
  • 411
  • 5
  • 22