Axios(在React Native中)没有调用本地服务器

36

我正在构建一个非常简单的API和React Native应用。服务器运行良好(已在PostMan中进行测试),但应用程序无法调用服务器。当axios必须发送POST请求时,它会阻塞(请参见下文)。

我很绝望 :-( 在这上面浪费了太多时间。如果你可以帮我……

这是我的登录页面代码。它派发操作创建者(与Redux一起使用)并提供电子邮件和密码:

...
const LogIn = React.createClass({
  submitLogin() {
    // log in the server
    if (this.props.email !== '' && this.props.psw !== '') {
      if (this.props.valid === true) {
        this.props.dispatch(logIn(this.props.email, this.props.psw));
      } else {
        this.props.dispatch(errorTyping());
      }
    }
  },
...

电子邮件地址和密码已成功检索并发送到操作创建器:

import axios from 'axios';
import { SIGNIN_URL, SIGNUP_URL } from '../api';
// import { addAlert } from './alerts';
exports.logIn = (email, password) => {
  return function (dispatch) {    
    console.log(email);
    console.log(password);
    console.log(SIGNIN_URL);
    return axios.post(SIGNIN_URL, { email, password })
    .then(
      (response) => {
        console.log(response);
        const { token, userId } = response.data;
        dispatch(authUser(userId));
      }
    )
    .catch(
      (error) => {
        console.log('Could not log in');
      }
    );
  };
};
const authUser = (userId) => {
 return {
 type: 'AUTH_USER',
 userId
 };
};
...

在 axios 调用之前的三个 console.log() 显示数据的方式是正确的。SIGNIN_URL 正好是我在 postman 中使用的相同地址。...但 axios 没有调用。

只是为了将所有的牌都揭示出来,这是我的 store:

import thunk from 'redux-thunk';
import { createStore, compose, applyMiddleware } from 'redux';
import { AsyncStorage } from 'react-native';
import { persistStore, autoRehydrate } from 'redux-persist';
import reducer from '../reducer';
const defaultState = {};
exports.configureStore = (initialState = defaultState) => {
 const store = createStore(reducer, initialState, compose(
 applyMiddleware(thunk),
 autoRehydrate()
 ));
 persistStore(store, { storage: AsyncStorage });
 return store;
};

在调试器中没有错误信息(除了 axios 调用给出的“无法登录”消息)

我使用的是 Windows 10,并且安装了:

"axios": "^0.15.3",
"react": "15.4.2",
"react-native": "0.38.0",
"redux": "^3.6.0"

即使我准备了一个简单的GET请求,而服务器应该返回一个简单的消息(在Postman和浏览器中测试过),但调用仍然失败:

exports.test = () => {
  return function () {
    return axios.get('https://localhost:3000/v1/test')
    .then(
      (response) => {
        console.log(response);
      }
    )
    .catch(
      (error) => {
        console.log('error');
      }
    );
  };
};

最后,我也尝试修改调用并添加了一个标题,如下所示,因为该API的编码接受JSON:

const head = {
  headers: { 'Content-Type': 'application/json' }
};

exports.test = () => {
  return function () {
    return axios.get('https://api.github.com/users/massimopibiri', head)
    .then(
      (response) => {
        console.log(response);
      }
    )
    .catch(
      (error) => {
        console.log('error');
      }
    );
  };
};

但即使这样也没用。希望有人能帮助我。其他类似的问题也没有解决。


附加信息:我正在使用Android 将以下程序相关的内容从英语翻译成中文。仅返回翻译后的文本: - Pibo
12个回答

64

这个解决方案来自另一个渠道,但我在这里发布它是为了帮助其他遇到相同问题的人。基本上,我使用Android AVD(模拟器)构建应用程序。但模拟器实际上是另一台机器,这就是为什么它无法调用localhost的原因。

为了解决这个问题,我不得不按照以下方式发送请求:

https://10.0.2.2:3000/v1/test

而不是:

https://localhost:3000/v1/test

你的本地证书是自签名的吗?你如何在没有证书文件路径验证错误的情况下调用https://localhost? - mrkpatchaa
除了我写的那个更改之外,我不需要做任何其他更改。它第一次尝试就成功了。所以我不知道如何帮助你。错误信息显示了什么? - Pibo
我遇到了 java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 的问题,因为我在本地使用了自签名证书。 - mrkpatchaa
1
我在使用Vue.js 2.0应用程序时遇到了同样的问题。在我的笔记本电脑上,后端服务器通信没有任何问题。然而,当我尝试在移动设备上访问时,我也无法从后端获取任何响应。我不得不更改axios的设置,以便它成功地到达我的后端服务器,如注释中所述,将其定位到我的本地机器(192.168.1.7)。感谢您的帮助。 - twknab
我无法让它工作,我的IP地址是10.0.0.155,我正在本地主机上运行IIS Express,端口号为localhost:44327。我尝试使用IPv4地址和端口44327进行https连接,也尝试了http端口,但都没有成功。 - Highspeed
@Pibo,虚拟主机应该怎么做? - Ganpat

27

如果您使用的是Mac,这个解决方案对我有用。我正在使用React Native和Android模拟器ADV。 Nexus Api 27

            axios.get('http://192.168.1.21:8686/api/v1/test')
            .then(response => console.log(response))
            .catch(err => console.log(err));

IP地址192.168.1.21来源于系统偏好设置 > 网络 > 高级 > TCP/IP > IPv4地址

我还测试了axios.get('http://10.0.2.2:8686/bec/api/v1/test'),其中10.0.2.2是虚拟机连接电脑的本地地址,但没有成功。


非常感谢,这个方法对我很有效。我坐了一个小时以为我的API出了问题,因为它可以使用我在网上找到的一些示例API,但不能使用我的本地主机。谢谢。 - Grand Skunk

14

您的模拟器是一种独立设备,不在同一IP(localhost或127.0.0.1)上运行,与您的Web浏览器、Postman或服务器不同。

为了从您的模拟器向服务器发送请求,您需要通过计算机IP地址访问服务器: 在Windows上,通过在命令提示符中运行ipconfig来获取您的IP地址

在Unix终端(Linux、Mac OS)上运行ifconfig以获取您的IP地址

您应该使用http://your_ip_address:port而不是http://localhost:port

我没有在Linux、Mac OS上测试过,但在Windows上完美运行!


1
这就是所谓的专业人士,看到了许多不同问题的答案,您没有提及任何代码,但您的解释解决了此问题。 - Santanu Biswas

13

1
这对我有用,因为我正在使用我的Android移动设备调试应用程序。 Android设备不知道我计算机上的“localhost”。因此,如果您正在使用Android设备进行调试,请改用“IP地址”而不是使用“localhost”。 - Gimnath

3
另一个解决方案是在本地计算机上使用管理员cmd命令创建托管网络:
netsh wlan set hostednetwork mode=allow ssid=wifi_name key=wifi_password
netsh wlan start hostednetwork

将您的设备连接到计算机的热点,然后运行以下命令获取计算机的IP地址:

ipconfig

现在获取IPV4地址并将其放在应用程序的axios/fetch URL上。
axios.get('https://192.168.137.1:3000/api')
.then(
  (response) => {
    console.log(response);
  }
)
.catch(
  (error) => {
    console.log('error');
  }
);

现在应该可以正常工作了!


2
我发现了另一个解决axios.get在react native中无法正常工作的问题的方法:
问题:对象不可见,错误:未处理的承诺。网络错误。
解决方案:使用以下命令: >>> npm install -g --save axios
而不是npm install --save axios,即使用-g。
还要检查模拟器是否有互联网连接。
如果您的模拟器没有互联网连接并显示错误,例如:DNS探测完成错误配置,则停止Android Studio模拟器并在终端中运行这两个命令。
1. C:\Users\Admin\AppData\Local\Android\sdk\emulator\emulator.exe -list-avds
我的输出:
Pixel_XL_API_27
执行完此步骤后,您将获得avd的名称。
例如:Pixel_XL_API_27
现在运行以下命令:
2. C:\Users\Admin\AppData\Local\Android\sdk\emulator\emulator.exe -avd Pixel_XL_API_27 -dns-server 8.8.8.8

1

解决此问题的另一种方法,如果通过其他方式连接不起作用。正如其他人所说,由于手机是一台不同的机器,您不能使用本地主机。但是您可以使用隧道。这将为您提供一个 URL(对整个互联网开放),以复制您的本地主机。

  1. 全局安装 localtunnel 包(yarn global add localtunnel)
  2. 确保您的服务器正在运行,并注意端口号(例如,http://localhost:8081)
  3. 在另一个终端/命令提示符中,运行 localtunnel 命令(对我来说,是 npx localtunnel --port 8081)。这将创建一个您可以从公开网络访问的服务器。
  4. 现在,您可以使用控制台中的 URL 替换您的 React Native 应用程序中的 URL

1
对我而言,'https://10.0.2.2:3000' 无法工作。我尝试通过 ngrok 将 localhost:3000 映射到一个 URL,并使用该 URL:
./ngrok http 3000(在终端上运行此命令将启动会话,并将全局 URL 映射到本地主机端口 3000)。请记住,为此您应该在系统上安装 ngrok。

1
我也遇到了类似的问题,我使用Expo CLI构建和运行我的React Native应用程序。我的后端Express API也在同一台机器上运行。因此,在我的情况下,Axios调用是从Android虚拟设备模拟器内部执行的,因此本地主机调用失败。所以,我使用了IP地址而不是localhost,这样就可以了!
如果您正在使用expo客户端,请在Metro Server页面上检查热点IP地址,例如192.168.x.x(在我的情况下,IP是这种类型)。
如果您没有使用expo,则请使用以下命令检查您的IP地址:
  • ipconfig /all(在Windows上)
  • ifconfig -a(在Linux / Mac上)
然后,在axios api调用中,使用http://192.168.x.x,如果您使用https,则使用https,但通常为了开发目的,您可以使用http。但是请确保在生产环境中,始终使用带有您的域或子域的https以提供额外的安全性。

0

尝试关闭防火墙,这对我有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接