代码之家  ›  专栏  ›  技术社区  ›  sjbuysse

反应服务单例替代方案

  •  2
  • sjbuysse  · 技术社区  · 7 年前

    我正在使用谷歌地图库制作一个ReactJS应用程序; 我正试图将大多数地图逻辑抽象为一项服务,以便将来如果我想的话,可以用传单交换谷歌地图库。

    它现在的工作方式是,我有一个组件加载地图库并将其附加到一个div onLoad

    onMapLoad={(map: Map) => {
        mapService.setMap(map);
        props.mapLoaded();
    }}
    

    例如,当地图上的某个标记被选中时,该服务还需要访问我的redux存储以调度操作。我在启动应用程序时设置了这个 index.tsx 文件

    const store = getStore();
    mapService.setStore(store);
    

    该服务本身是一个单例服务,但我想知道是否有更好的模式用于React或只是一般情况。我将发布该服务的较短版本,为简洁起见,保留了一些方法。有没有人有可能改进这种做法的模式建议?

    interface MapService {
        predictPlaces: (query: string) => Observable<AutocompletePrediction[]>;
        setStore: (store: Store<StoreState>) => void;
        addMarkerToMap: (place: Place) => void;
        centerMapAroundSuggestion: (suggestion: Suggestion) => void;
        setMap: (newMap: Map) => void;
    }
    
    let predictService: google.maps.places.AutocompleteService;
    let geocoder: google.maps.Geocoder;
    let map: Map;
    let store: Store;
    let markers: google.maps.Marker[] = [];
    
    const setMap = (newMap: Map) => {
        map = newMap;
    }
    
    const setStore = (store: Store) => {
        store = Store;
    }
    
    const centerMapAroundSuggestion = (suggestion: Suggestion) => {
        if (!map) {
            throwGoogleMapsNotLoaded();
        }
        if (!geocoder) {
            geocoder = new google.maps.Geocoder();
        }
        ... further implementation ...
    }
    
    const predictPlaces = (query: string): Observable<AutocompletePrediction[]> => {
        if (!map) {
            return of([]);
        }
        if (!predictService) {
            predictService = new google.maps.places.AutocompleteService();
        }
        ... further implementation ...
    }
    
    const addMarkerToMap = (place: Place, onSelect: () => void) => {
        const marker = createMarker(place, onSelect);
        markers.push(marker);
    }
    
    const createMarker = (place: Place): Marker => {
        if (!map) {
            throwGoogleMapsNotLoaded();
        }
        const marker = new google.maps.Marker({
            ...options...
        });
        marker.addListener('click', () => {
            createInfoWindow(marker)
            if(!!store) {
                store.dispatch(createMarkerClicked(place))
            }
        });
        ... further implementation ...
    }
    
    function throwGoogleMapsNotLoaded() {
        throw new Error('Google maps not loaded');
    }
    
    export const mapService: MapService = {
        predictPlaces,
        addMarkerToMap,
        setMap,
        setStore,
        centerMapAroundSuggestion
    }
    
    0 回复  |  直到 7 年前