多裝置(手機)同步 - 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>