You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

相同React Native推送通知代码在新应用触发Promise拒绝问题排查

问题分析与解决方案

你的代码在新项目中触发Promise拒绝,核心问题集中在错误捕获缺失、环境变量写法错误以及无效令牌处理不当这几点:

1. 未全面捕获Promise错误

原代码仅捕获了AWS操作环节的错误,但未处理registerForPushNotificationsAsync自身可能抛出的Promise拒绝(比如getDevicePushTokenAsync调用失败);同时当该函数返回undefined(权限未授予、模拟器环境)时,后续AWS操作传入无效令牌也会触发拒绝。

2. 环境变量写法错误

你把process.env.XXX包裹在字符串引号内(比如"process.env.AWS_REGION"),这会直接将字符串字面量传给AWS配置,而非读取实际环境变量值,导致AWS SDK初始化失败,触发Promise拒绝。

3. 无效令牌未做拦截

当权限未授予或在模拟器运行时,registerForPushNotificationsAsync返回undefined,后续直接用这个值调用AWS的createPlatformEndpoint,会因参数缺失抛出错误。


修正后的完整代码

import { useState, useEffect } from "react";
import { Text, View, Platform } from "react-native";
import * as Device from "expo-device";
import * as Notifications from "expo-notifications";
import AWS from "aws-sdk";

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

export default function App() {
  const [deviceToken, setDeviceToken] = useState("");

  useEffect(() => {
    // 封装所有异步操作,统一用try/catch捕获错误
    const initPushNotifications = async () => {
      try {
        // 修复环境变量写法:直接引用process.env,不要包裹在字符串中
        AWS.config.update({
          region: process.env.AWS_REGION,
          accessKeyId: process.env.AWS_ACCESS,
          secretAccessKey: process.env.AWS_SECRET,
        });

        const token = await registerForPushNotificationsAsync();
        if (!token) {
          console.log("未获取到有效设备令牌,终止注册流程");
          return;
        }
        setDeviceToken(token);

        const SNS = new AWS.SNS({ correctClockSkew: true });
        const platformApplicationArn = 
          Platform.OS === "android"
            ? process.env.FIREBASE_ARN
            : process.env.IOS_ARN;

        // 创建平台端点
        const endpointParams = {
          PlatformApplicationArn: platformApplicationArn,
          Token: token,
        };
        const createEndpointResponse = await SNS.createPlatformEndpoint(endpointParams).promise();
        const endpointArn = createEndpointResponse.EndpointArn;

        // 订阅主题
        const subscribeParams = {
          TopicArn: process.env.TOPIC_ARN,
          Protocol: "Application",
          Endpoint: endpointArn,
        };
        await SNS.subscribe(subscribeParams).promise();
        console.log("设备已成功注册到AWS SNS");
      } catch (err) {
        console.error("推送通知初始化失败:", err);
      }
    };

    initPushNotifications();
  }, []);

  return (
    <View
      style={{
        flex: 1,
        alignItems: "center",
        justifyContent: "space-around",
        marginHorizontal: 25,
      }}
    >
      <Text>你的Expo推送令牌: {deviceToken} </Text>
    </View>
  );
}

async function registerForPushNotificationsAsync() {
  if (!Device.isDevice) {
    alert("必须使用物理设备测试推送通知");
    return null;
  }

  // 检查并请求权限
  let { status: existingStatus } = await Notifications.getPermissionsAsync();
  if (existingStatus !== "granted") {
    const { status } = await Notifications.requestPermissionsAsync();
    existingStatus = status;
  }
  if (existingStatus !== "granted") {
    alert("获取推送通知权限失败!");
    return null;
  }

  // 获取设备令牌,调用失败会抛出错误,被上层try/catch捕获
  const tokenData = await Notifications.getDevicePushTokenAsync();
  console.log("设备令牌:", tokenData.data);
  return tokenData.data;
}

额外注意事项

  • 环境变量配置: 确保新项目已正确配置环境变量,比如使用expo-env或dotenv,在项目根目录创建.env文件存放AWS相关配置。
  • 设备要求: 测试时必须使用物理设备,模拟器无法获取有效推送令牌。
  • AWS权限验证: 确认AWS账号的AccessKey拥有SNS的CreatePlatformEndpoint和Subscribe权限,避免因权限不足触发错误。

内容的提问来源于stack exchange,提问作者Dan Cruz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 00:01:30