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

如何在React Native中订阅Salesforce Platform Event通知

在React Native中使用Salesforce Pub/Sub API订阅Platform Events

原代码的核心问题

  1. 订阅函数未触发:setPEvents仅定义但从未被调用,拿到Salesforce会话凭证后没有执行订阅逻辑
  2. API端点错误:Pub/Sub API的订阅端点不是/event/${eventName}/subscriptions,正确的通用订阅路径为/services/data/vXX.X/pub-sub/subscriptions
  3. 缺少消息拉取逻辑:创建订阅只是第一步,单次POST请求无法持续接收事件推送,需要通过轮询拉取后续消息

修正后的完整实现代码

import {View, Text} from 'react-native';
import React, { useEffect, useState } from 'react';
import { oauth } from 'react-native-force';

function History() {
    const [session, setSession] = useState(null);
    const eventName = "Test_PE__e";
    const [replayMode] = useState("ALL"); // ALL接收所有事件,LATEST只接收订阅后的新事件
    const [subscription, setSubscription] = useState(null);
    const [receivedEvents, setReceivedEvents] = useState([]);
    let pollTimer = null;

    // 处理登录与会话初始化
    useEffect(() => {
        oauth.getAuthCredentials(
            (authData) => {
                console.log("已获取会话凭证", authData);
                setSession(authData);
            },
            () => {
                oauth.authenticate(
                    (newAuthData) => setSession(newAuthData),
                    (error) => console.log('认证失败:' + error)
                );
            }
        );

        // 组件卸载时清理轮询定时器
        return () => {
            if (pollTimer) clearInterval(pollTimer);
        };
    }, []);

    // 会话更新时自动创建订阅
    useEffect(() => {
        if (session) initSubscription(session);
    }, [session]);

    // 创建Pub/Sub订阅
    async function initSubscription(session) {
        const headers = new Headers({
            'Authorization': `Bearer ${session.accessToken}`,
            'Content-Type': 'application/json'
        });
        const requestBody = {
            "topicName": `/event/${eventName}`,
            "replayPreset": replayMode
        };
        const subscribeUrl = `${session.instanceUrl}/services/data/v57.0/pub-sub/subscriptions`;

        try {
            const response = await fetch(subscribeUrl, {
                method: 'POST',
                headers: headers,
                body: JSON.stringify(requestBody)
            });

            if (!response.ok) throw new Error(`订阅请求失败,状态码: ${response.status}`);
            
            const subInfo = await response.json();
            setSubscription(subInfo);
            console.log("订阅成功,ID:", subInfo.id);
            
            // 启动消息轮询
            startMessagePolling(subInfo.id, session);
        } catch (err) {
            console.log('订阅出错:', err);
        }
    }

    // 轮询拉取事件消息
    async function startMessagePolling(subId, session) {
        const headers = new Headers({
            'Authorization': `Bearer ${session.accessToken}`
        });
        const pollUrl = `${session.instanceUrl}/services/data/v57.0/pub-sub/subscriptions/${subId}/messages`;

        pollTimer = setInterval(async () => {
            try {
                const response = await fetch(pollUrl, {
                    method: 'GET',
                    headers: headers,
                    signal: AbortSignal.timeout(30000) // 30秒超时避免请求挂起
                });

                if (!response.ok) {
                    if (response.status === 404) {
                        console.log("订阅已失效,重新创建订阅");
                        clearInterval(pollTimer);
                        initSubscription(session);
                    }
                    return;
                }

                const messageData = await response.json();
                if (messageData.messages?.length) {
                    // 追加新事件到列表
                    setReceivedEvents(prev => [...prev, ...messageData.messages]);
                }
            } catch (err) {
                console.log('拉取消息出错:', err);
            }
        }, 5000); // 每5秒轮询一次,可根据业务调整间隔
    }

    return (
      <View style={{flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20}}>
            <Text style={{fontSize: 18, marginBottom: 10}}>已订阅事件: {eventName}</Text>
            <Text>累计接收事件: {receivedEvents.length}</Text>
            {receivedEvents.map((evt, idx) => (
                <Text key={idx} style={{marginTop: 8, fontSize: 12}}>
                    {JSON.stringify(evt.payload)}
                </Text>
            ))}
        </View>
    );
}

export default History;

关键注意事项

  • 权限配置:确保Salesforce用户已分配PubSubAPI权限集,且对目标Platform Event拥有读权限
  • API版本适配:使用支持Pub/Sub API的版本(v53.0及以上),建议使用最新稳定版
  • 轮询优化:可根据业务需求调整轮询间隔,也可使用长轮询模式(设置wait参数)减少请求次数
  • 错误处理:需处理订阅失效、网络异常等场景,避免应用静默崩溃

内容的提问来源于stack exchange,提问作者Fırat DİKMEN

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:35:27