多设备(手机)同步 - React Native
<p>我正在尝试创建 Lightshow,它将同时在所有用户的移动设备上启动(最多可以有 2000-3000 个用户)。所有用户都将使用互联网(Wi-Fi 或移动数据)。在我们的 FE,我们使用 Apollo 进行订阅,这就像一个魅力。</p>
<p>但问题是,用户 A 可以比用户 B 更快地获取订阅事件。这意味着用户 A 将比用户 B 更早开始玩游戏,这是一个问题,因为我们有 lighshow 架构,而用户可以'不能早点或晚点开始。作为用户,您会立即看到差异,而且看起来不太好。</p>
<p>我看到的是延迟差异可以达到300ms。 android (小米 9) 与 ios (iPhone11) 之间的时间大多约为 180ms+-。如果我们比较两台 iOS 设备 iPhone 11 和 iPhone 13,差异约为 50-100 毫秒。对于所有设备,有没有办法消除这种差异,或者至少将其降低到 40-60 毫秒?</p>
<p>从 BE 开始,我们发送服务器时间(utc+0),灯光秀将以时间戳开始 => 在 FE 中,我添加 10 秒来为所有设备提供解决该功能的时间,因此启动被延迟 -> "时间戳 + 10 秒”。</p>
<p>在 FE 中,我使用库“react-native-ntp-client”在所有类型的设备上获得相同的时间(ios/android,因为我发现每个设备的时间略有不同)。然后我计算“start”和“ntpTime”之间的差异,并将其作为超时提供给我的 setTimeout 函数,这将触发灯光秀的开始。</p>
<p>下面我提供了示例,说明我如何使用灯光秀所在的屏幕。</p>
<pre class="brush:php;toolbar:false;">import dayjs from 'dayjs';
import ntpClient from 'react-native-ntp-client';
export const LightshowScreen: React.FC<
LightshowScreenProps<'Lightshow'>
> = ({route}) => {
const {data, loading} = useSubscription(JOIN_LIGHTSHOW_SUBSCRIPTION, {
variables: {lightshowId: route.params.lightshow.id},
});
useEffect(() => {
const getServerTime = async (lightshowStartAt: number) => {
// Delay start 10s to provide enough time to finish our functions - lightshowStartAt is timestamp from our server
const lightshowStart = dayjs.unix(lightshowStartAt).add(10, 's');
ntpClient.getNetworkTime('time.cloudflare.com', 123, (error, date) => {
if (error) {
console.error('Cant connect', error);
return;
}
console.log('NTP client date - ', date); // Mon Jul 08 2013 21:31:31 GMT+0200 (Paris, Madrid (heure d’été))
let ntpTime = dayjs(date);
// Diff in ms
const diff = lightshowStart.diff(ntpTime);
// After this timeout all devices should start play at the same time
setTimeout(() => {
lightshowStartHandler();
}, diff);
});
};
if (data && data?.joinLightshow.started) {
const lightshowData = data.lightshow;
getServerTime(lightshowData.startedAt);
}
}, [data]);
useEffect(() => {
if (data && data?.joinLightshow?.finished) {
lightshowFinishHandler();
}
}, [data]);
return (
<View style={style.container}>
....
</View>
);
};</pre>
<p>感谢您的所有评论和想法;)</p>