Каков наилучший способ сделать функцию для получения текущих пользовательских координат в RN - PullRequest
0 голосов
/ 15 мая 2018

Я хочу создать одну функцию для получения пользовательских координат и почему-то обнаружил, что не уверен, что мой подход достаточно хорош.
Я хотел бы знать, как другие пишут эту функцию для работы 100% уверен на IOS и на Android .
Теперь у меня есть что-то вроде этого:

function getUserLocation(callback: func) {
  Permissions.check('location')
  .then(response => {
    if (response == 'authorized') {
      navigator.geolocation.getCurrentPosition(
        (location) => {
          callback({
              latitude: location.coords.latitude, 
              longitude: location.coords.longitude
            }, response);
        },
        (error) => {
          callback(null);
        },
        Platform.OS === 'android' ? null : {enableHighAccuracy: true, timeout: 100000, maximumAge: 1000}
      );
    } else {
      callback(null, response);
    }
  })
}

Итак, вы можете видеть, что я хочу использовать эту функцию, чтобы вызывающая сторона могла знать, разрешено ли использование местоположений и получает ли оно текущие координаты.
Я пытаюсь научиться:

1. Сделайте так, чтобы эта функция была ожидаемой .
2. Как другие работают так ( для обеих ОС ) и работают на 100% одинаково.

Ответы [ 3 ]

0 голосов
/ 22 мая 2018

В общем, для меня подход не самый лучший. Есть ли причина, по которой вы хотите тянуть?

Обе ОС имеют режим push, в котором вы отслеживаете положение, основываясь на изменении положения, это лучше для пользователей, работающих от батареи, а также для обработки вашего приложения. Также сделать что-то доступным будет блокирующим вызовом, который вы на самом деле не хотите делать много.

У React Native есть метод navigator.geolocation.watchPosition, здесь вы можете найти ссылку . Вы можете определить параметры, касающиеся точности, времени ожидания и т. Д.

Следующая функция использовалась в случае с redux, поэтому каждый раз, когда redux-thunk отправляет события в виде обещаний, каждый раз пересчитывать состояние в редукторах, но ее легко адаптировать, изменяя функцию обратного вызова, чтобы делать все, что вы хотите.

let geolocationSettings = {enableHighAccuracy: true, timeout: 5000, maximum: 5000, distanceFilter:10}

function setPositionWatch(dispatch,geolocationSettings){
    positionWatcher = navigator.geolocation.watchPosition(
        (pos) => {
            dispatch({
                type: types.NEW_POSITION,
                state: pos
            })
        },
        () => {
            dispatch({
                type: types.ERROR_POSITION
            })
        },
        geolocationSettings)
}

По сути, для этого механизма push вы предоставляете обратный вызов для правильного поведения, неправильного поведения и опций. и когда вы хотите прекратить сбор информации о местоположении, вы делаете clearWatch.

0 голосов
/ 25 мая 2018

Сделайте асинхронную версию getCurrentPosition, вы можете добавить эту функцию в navigator.geolocation.

async function getCurrentPosition(options) {
    return new Promise((resolve, reject) => {
        navigator.geolocation.getCurrentPosition(
            position => resolve(position.coords),
            error => reject(error),
            options
        });
    });
}

Следующая функция - это то, что вы хотите. Лучше выдавать исключение, когда не авторизовано, потому что в любом случае вам нужно попробовать / поймать из-за getCurrentPosition.

const locationOptions = Platform.OS === 'android' ? null : 
    { enableHighAccuracy: true, timeout: 100000, maximumAge: 1000 };

async function getUserLocation() {
    let permission = await Permissions.check('location');
    if (permission !== 'authorized') {
        throw new Error('Not authorized: ' + permission);
    }

    return await getCurrentPosition(locationOptions);
}

Как использовать:

try {
    let location = await getUserLocation(); // { latitude, longitude }
} catch (error) {
    Alert.alert(error.message);
}
0 голосов
/ 21 мая 2018

На ваш вопрос есть две части

1. Сделайте так, чтобы эта функция была ожидаемой.

Это ответственно, предоставляя вам логику того, как это сделать. Awaitable - это не что иное, как асинхронная функция или что-то, что возвращает обещание. Если вы хотите пойти по пути async, вам нужно сначала создать версию getCurrentPosition, которая возвращает обещание. Это можно сделать, как показано ниже

function getCurrentLocation(options) {
  return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(resolve, ({code, message}) =>
      reject(Object.assign(new Error(message), {name: "PositionError", code})),
      options);
    });
};

PS: кредиты на https://stackoverflow.com/a/44439358/2830850 для вышеуказанного кода

Теперь вы можете переписать свой код, как показано ниже

async function getUserLocation() {
  let response = await Permissions.check('location')
  let options = Platform.OS === 'android' ? null : {enableHighAccuracy: true, timeout: 100000, maximumAge: 1000}

  if (response == 'authorized') {
      return await getCurrentLocation(options)
  }

  return null;
}

В случае, если вы не хотите идти promise, как это было бы ниже

function getUserLocation() {
    return new Promise((resolve, reject) => {
        Permissions.check('location')
            .then(response => {
                if (response == 'authorized') {
                    navigator.geolocation.getCurrentPosition(
                        (location) => {
                            resolve({
                                latitude: location.coords.latitude,
                                longitude: location.coords.longitude
                            });
                        },
                        (error) => {
                            reject(error);
                        },
                        Platform.OS === 'android' ? null : { enableHighAccuracy: true, timeout: 100000, maximumAge: 1000 }
                    );
                } else {
                    resolve(null);
                }
            })
    });
}

Одна ключевая вещь здесь, в отличие от обратных вызовов, обещает разрешить одно значение, что означает, что вам нужно использовать объекты для возврата нескольких параметров.

2. Как другие работают так (для обеих ОС) и работают на 100% одинаково.

Здесь ваш вопрос становится самоуверенным, я могу использовать другой подход, вы можете сделать что-то другое, а другой человек может сделать что-то другое. Но я все еще буду обсуждать несколько возможностей.

Разделить на несколько функций

function getUserLocation() {
   if (Platform.OS === 'android')
   {
       return getUserLocationAndroid();
   } else {
       return getUserLocationIOS();
   }
}

Ведение пар ключ-значение

У вас может быть код, который автоматически связывает функцию в зависимости от ОС.

Utils = {
   getFunction(name) {
      if ((name + Platform.OS) in this)
          return this[name + Platform.OS]
      return this[name];
   }
   getLocation: function() {}
   //getLocationandroid: function() {}
}

Таким образом, по умолчанию у вас будет getLocation для сервера обеих ОС, но в случае слишком большого отклонения кода одной из ОС вы создадите новую функцию для той же самой. Код будет выглядеть примерно так:

Utils.getFunction("getLocation")(...)

Одна функция с разветвлением

Это ваш нынешний подход. Я бы придерживался этого, пока функции легко понять, и есть четкое намерение, какая часть кода выполняет специфические для платформы вещи

Опять-таки, здесь можно указать еще 10 различных способов, но в конечном итоге это будет зависеть от одного: что вам легче поддерживать, понимать использование. Некоторые подходы также зависят от конкретного случая, где вы можете смешать несколько подходов на основе варианта использования

...