尝试通过调用使用 axios 的函数(异步)来填充数组,并且函数 returns 在填充数组之前未定义
Trying to fill an array by calling a function (async) that uses axios, and the function returns undefined before filling array
我有两个 jsx 文件。 TodoAPI.jsx 有一个名为 getTodos() 的函数,它使用 axios 从 mongodb 数据库中获取数据,并且成功地完成了测试。此函数通常由 TodoApp.jsx 中的某些行调用,显然整个代码在 getTodos() 甚至 returns 数组之前执行。因此,所有本应由 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,但我确定问题出在上面的代码中。
您不能在 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;
})
}
我有两个 jsx 文件。 TodoAPI.jsx 有一个名为 getTodos() 的函数,它使用 axios 从 mongodb 数据库中获取数据,并且成功地完成了测试。此函数通常由 TodoApp.jsx 中的某些行调用,显然整个代码在 getTodos() 甚至 returns 数组之前执行。因此,所有本应由 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,但我确定问题出在上面的代码中。
您不能在 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;
})
}