【问题标题】:React Native atob() / btoa() not working without remote JS debuggingReact Native atob() / btoa() 在没有远程 JS 调试的情况下无法工作
【发布时间】:2017-08-07 09:03:02
【问题描述】:

我有一个反应原生的测试应用程序,当我远程启用调试 js 时一切正常。运行后,它在设备(来自 XCode)和模拟器中运行良好:

react-native run ios

问题是,如果我停止远程 js 调试,登录测试不再起作用。登录逻辑非常简单,我正在获取一个 api 来测试登录,API 端点是通过 https。

我需要改变什么?

更新:此代码在启用 JS Debug Remote 的情况下完美运行,如果我禁用它,它将不再工作。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react'
import {
  AppRegistry,
  StyleSheet,      
  View,
  Button,
  Alert
} from 'react-native'

export default class MyClass extends Component {

  constructor (props) {
    super(props)
    this.testFetch = this.testFetch.bind(this)
  }

  async testFetch () {
    const email = 'email@example.com'
    const password = '123456'

    try {
      const response = await fetch('https://www.example.com/api/auth/login', {
        /* eslint no-undef: 0 */
        method: 'POST',
        headers: {
          'Accept': 'application/json' /* eslint quote-props: 0 */,
          'Content-Type': 'application/json',
          'Authorization': 'Basic ' + btoa(email + ':' + password)
        }

      })
      Alert.alert('Error fail!', 'Fail')
      console.log(response)
    } catch (error) {
      Alert.alert('Error response!', 'Ok')
    }
  }

  render () {
    return (
      <View style={styles.container}>            
        <Button
          onPress={this.testFetch}
          title="Test me!"

        />            
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF'
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5
  }
})

AppRegistry.registerComponent('testingReactNative', () => MyClass)

谢谢。

【问题讨论】:

  • 您至少需要在此处添加一些代码。 JS远程调试不太可能出现这个错误。
  • 嗨@zvona 我已经用代码更新了这个问题......谢谢。
  • 好的,我的错误是“btoa”在没有调试的情况下执行时未定义......但是为什么呢? :)
  • 哦,很好。 atobbtoa 在没有调试器的情况下无法工作(无法解释原因)。
  • 和这个问题一样,你将不允许使用一些 es6 特性 react native 不支持但 chrome 支持,当你将 react-native 应用程序连接到 chrome 远程调试器时,你会更改 js 运行时环境到 chrome。这就是为什么你不能在没有远程调试器的情况下使用某些功能,而 polyfill 是解决方案。

标签: react-native


【解决方案1】:

给你 (https://sketch.expo.io/BktW0xdje)。创建一个单独的组件(例如 Base64.js),将其导入即可使用。比如Base64.btoa('123');

// @flow
// Inspired by: https://github.com/davidchambers/Base64.js/blob/master/base64.js

const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const Base64 = {
  btoa: (input:string = '')  => {
    let str = input;
    let output = '';

    for (let block = 0, charCode, i = 0, map = chars;
    str.charAt(i | 0) || (map = '=', i % 1);
    output += map.charAt(63 & block >> 8 - i % 1 * 8)) {

      charCode = str.charCodeAt(i += 3/4);

      if (charCode > 0xFF) {
        throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
      }

      block = block << 8 | charCode;
    }

    return output;
  },

  atob: (input:string = '') => {
    let str = input.replace(/=+$/, '');
    let output = '';

    if (str.length % 4 == 1) {
      throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
    }
    for (let bc = 0, bs = 0, buffer, i = 0;
      buffer = str.charAt(i++);

      ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
        bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
    ) {
      buffer = chars.indexOf(buffer);
    }

    return output;
  }
};

export default Base64;

【讨论】:

  • 谢谢,我刚刚安装了 base-64 npm 包;)npmjs.com/package/base-64
  • 是的,同意@chemitaxis,imo 最好使用包而不是复制代码。也许你可以用几个选项更新你的答案。
  • 使用包意味着将所有不必要的东西安装到项目中,而您只需复制必要的代码以满足特定需求。这不是正确的方式,也不是更好的方式。这是最糟糕的。谢谢你的回答。
【解决方案2】:

这就是我修复它的方式。正如@chemitaxis 建议的那样,从 NPM 添加 base-64 模块:

npm i -S base-64

在此基础上,我提出了几种使用方式:

导入到你需要的文件中

然后,您可以使用别名导入“编码”和“解码”方法,这样:

import {decode as atob, encode as btoa} from 'base-64'

当然,使用别名是可选的。

Polyfill 方式

您可以在 React Native 上将 atobbtoa 设置为全局变量。然后,您无需在需要的每个文件上导入它们。您必须添加以下代码:

import {decode, encode} from 'base-64'

if (!global.btoa) {
    global.btoa = encode;
}

if (!global.atob) {
    global.atob = decode;
}

您需要将它放在index.js 的开头,以便在另一个文件使用atobbtoa 之前加载它。

我建议你将它复制到一个单独的文件中(比如说 base64Polyfill.js),然后在 index.js 上导入它

【讨论】:

  • 此代码工作正常,但在发布 apk 中,它不起作用。有什么办法解决吗??
  • 这太棒了!谢谢你。我能够使用它来解码 JWT:const [encodedHeader, encodedBody, signature] = token.toString().split(".");const decoded = JSON.parse(atob(encodedBody));
  • @RaikumarKhangembam 你解决了这个问题吗?
【解决方案3】:

您的问题的主要部分已得到解答,但我发现对于启用远程调试的原因仍有一些不确定性。

在远程调试时,JavaScript 代码实际上是在 Chrome 中运行,并且虚拟 dom 的差异正在通过网络套接字与本机应用程序进行通信。

http://facebook.github.io/react-native/docs/javascript-environment

atobbtoa 在浏览器的上下文中可用,这就是它在那里工作的原因。

但是,当您停止调试时,JavaScript 会再次在您的设备或模拟器上的进程中进行解释,而该进程无法访问浏览器提供的功能。

【讨论】:

  • 这个。当我(由于我的错误)以错误的方式使用本机 js 排序功能时,我遇到了执行差异。数组在有和没有 js 调试的情况下排序不同,所以我猜可能产生意外结果的代码的每一部分都容易受到此影响。
猜你喜欢
  • 2017-06-11
  • 1970-01-01
  • 2017-03-01
  • 2018-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 2012-04-01
相关资源
最近更新 更多