Как синхронно обновлять значение после вызова Ajax

#javascript #node.js #arrays #reactjs #express

#javascript #node.js #массивы #reactjs #экспресс

Вопрос:

Я извлекаю данные с моего серверного сервера node (express) для интерфейса react. Но когда я пытаюсь получить доступ к значениям индекса массива, я получаю вывод как неопределенный. Я уверен, что здесь что-то не так. Буду признателен, если кто-нибудь сможет мне помочь.

Вот мой код на стороне сервера:

 const companyDetails = [];

companies.forEach((company) => {
    companyDetails.push(company);  
});

app.get("/api/companies", (req, res) => {
    res.json(companyDetails)
});
 

Вот мой код на стороне клиента:

 let arr = [];

    function fetchComNames() {
        axios.get('/api/companies').then(res => {
          for(let i=0; i<=4; i  ) {
              arr.push(res.data[i].name)
          }
        })
    }

    fetchComNames();

    console.log(arr[0]);   //undefined
 

Но когда я console.log(arr); распечатываю массив. Я просто не могу получить доступ к каждому значению индекса отдельно.

Вот выход, который откладывает quot;arrquot;, когда я не указываю индекс

Ответ №1:

 (async () => {
    const arr = [];

    // Marking this function as async function so that 
    // we can use await to wait until result returning 
    // before further executing code below
    async function fetchComNames() {
        // I don't have access to you API
        // I resolve data after 1 second to simulate Ajax call here
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                resolve({
                    data: [{
                        name: "1"
                    }, {
                        name: "2"
                    }, {
                        name: "3"
                    }, {
                        name: "4"
                    }]
                });
            }, 1000);
        }).then(res => {
            return res.data.map(each => each.name)
        });
    }

    // You are calling Ajax call via Axios, which is a Promise. 
    // It is executed asyncrhoniously. 
    // If you need to use result from this call, 
    // you need to wait until result returning from async call. 
    // You can achieve it with await.
    
    // Update existing array
    arr.push(...(await fetchComNames()));

    // After await, arr should contain result you expected.
    console.log(arr[0]);

    // There reason why your version is not working 
    // is because you are accessing the first cell of arr 
    // wihich is still empty as the Axios is still running 
    // and you are not waiting until it returns result.
})();
 

Комментарии:

1. Большое спасибо за объяснение. Но мне нужно получить доступ к значениям этого массива из этой функции. Кажется, я не могу сделать это вне этой функции. Могу ли я как-нибудь это сделать?

2. Пожалуйста, дайте мне больше кода. Если все, что вам нужно, это добавить больше элементов в существующий массив, это не проблема, я обновлю свой код

3. Это решает мою проблему, большое спасибо, вы очень помогли!

Ответ №2:

Проблема здесь в том, что axios вызов — это async вызов, и выполнение вашего кода таково sync , что при выполнении этого кода javascript sync сначала выполняется код, а затем async тот, поэтому в этом случае строка кода onsole.log(arr[0]); выполняется до того, как ответ придет с сервера

Ответ №3:

Вызовы API являются асинхронными, поэтому вы обращаетесь к массиву до того, как в нем появятся его значения. Попробуйте пометить свою заключающую функцию как асинхронную и ожидать получения axios, чтобы вызов был принудительно синхронным.

 let arr = [];

    async function fetchComNames() {
      const fetched = await axios.get('/api/companies');
          for(let i=0; i<=4; i  ) {
              arr.push(fetched.data[i].name)
          }
        
    }

    fetchComNames();

    console.log(arr[0])
 

Комментарии:

1. Тем не менее, это даст undefined

Ответ №4:

Добавление к приведенному ниже ответу fetchComNames асинхронно обновляется arr при использовании вызова API. Вы получаете доступ к данным до того, как они были обновлены, поэтому получаете undefined .

Вы можете попробовать это.

     
const fetchComNames = async () => {
    try {
      const response = await axios.get('/api/companies')
      const array = response.data.map(c => c.name)
      OR
      const array = []
      for (let i = 0; i<= 4; i  ) {
        array.push(response.data[i].name)
      }
      console.log(array[0])
    } catch(err) {
      console.error(err)
    }
}

fetchComNames()