【问题标题】:Trying to fill an array by calling a function (async) that uses axios, and the function returns undefined before filling array试图通过调用使用axios的函数(异步)来填充数组,并且函数在填充数组之前返回undefined
【发布时间】:2017-11-04 09:56:37
【问题描述】:

我有两个 jsx 文件。 TodoAPI.jsx 有一个名为 getTodos() 的函数,它使用 axios 从 mongodb 数据库中获取数据,并且如测试所示成功。此函数通常由 TodoApp.jsx 中的某些行调用,显然整个代码在 getTodos() 甚至返回数组之前执行。因此,所有应该由 getTodos() 填充的数组仍然未定义。我通过在 TodoApp.jsx 中使用 setTimeout(function(){ console.log(TodoAPI.getTodos()); }, 3000); 来确保我没有错,它实际上打印了数组。

如何确保 getTodos() 在其余代码开始之前完成?还是有更好的解决方案?

以下是代码的相关部分: TodoAPI.jsx:

var $ = require('jquery');
import axios from 'axios';

module.exports = {
  setTodos: function (todos) {
    if ($.isArray(todos)) {
      localStorage.setItem('todos', JSON.stringify(todos));
      return todos;
    }
  },
  getTodos: function () {
    let todos = [];
    axios({
      method: 'get',
      //url:'https://nameless-island-69625.herokuapp.com/todos',
      url: 'http://localhost:3000/todos',
      headers:{ 
        'x-auth': localStorage.getItem('x-auth') 
      }
    }).then(function(response) {
      todos = $.extend(true, [], response.data.todos);
      console.log('successful response from todos');
    }).then(() => {
      console.log(todos);
      return todos;
    }).catch((e) => {
      console.log('failed response from todos');
      console.log(e);
    });
    // return [{name:'asd'},{name:'qwe'},{name:'fgd'},];
  },

TodoApp.jsx:

var React = require('react');
var uuid = require('node-uuid');
var moment = require('moment');
const axios = require('axios');

var TodoList = require('TodoList');
var AddTodo = require('AddTodo');
var TodoSearch = require('TodoSearch');
var TodoAPI = require('TodoAPI');


var TodoApp = React.createClass({
  getInitialState: function () {
    return {
      showCompleted: false,
      searchText: '',
      todos: TodoAPI.getTodos()
    };
  },

其余代码可以在here找到,但我确信问题出在上面的代码中。

【问题讨论】:

  • 你有没有考虑在getTodos: function () {返回一些东西
  • 是的,我尝试在外部返回 .then() 但我遇到了同样的问题,只是这次返回的是空数组而不是未定义的数组。问题是函数在数据到达之前就完成了。

标签: javascript node.js reactjs axios


【解决方案1】:

您不能在getInitialState 中分配todos 状态,因为api 调用是异步的。而是在componentDidMount 中设置todos。比如:

componentDidMount() {
  axios.get('http://localhost:3000/todos')
    .then(res => {
      this.setState({ todos: res.data.todos });
    });
}

如果您希望在单独的文件中调用 api,请确保在您的函数中 return axios(... 并在 componentDidMount 中执行以下操作:

componentDidMount() {
  getTodos().then(todos => {
    this.setState({ todos });
  });
}

在这种情况下,您的 getTodos 函数可能如下所示:

getTodos: function () {
  return axios({
    method: 'get',
    url: 'http://localhost:3000/todos',
    headers:{ 
      'x-auth': localStorage.getItem('x-auth') 
    }
  }).then(function(response) {
    return response.data.todos;
  })
}

【讨论】:

  • 非常感谢。我使用 componentDidMount() 修改了我的代码,如下所示:var TodoApp = React.createClass({ getInitialState: function () { return { showCompleted: false, searchText: '', todos: [] }; }, componentDidMount: function() { TodoAPI.getTodos().then(todos => { console.log(todos); this.setState({ todos }); }); },
猜你喜欢
  • 1970-01-01
  • 2015-10-02
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 2019-04-30
  • 2021-10-04
  • 1970-01-01
  • 2021-06-25
相关资源
最近更新 更多