【问题标题】:React Native: Can't get (apparently async) function to finish before moving on [duplicate]React Native:在继续[重复]之前无法完成(显然是异步的)功能
【发布时间】:2020-04-11 05:46:10
【问题描述】:

使用 React Native 和 @mauron85/react-native-background-geolocation,我正在尝试创建一个函数来根据后台地理位置是否处于活动状态返回 true/false。

在文档中,我们看到了一个例子:

    BackgroundGeolocation.checkStatus(status => {
      console.log('[INFO] BackgroundGeolocation service is running', status.isRunning);
      console.log('[INFO] BackgroundGeolocation services enabled', status.locationServicesEnabled);
      console.log('[INFO] BackgroundGeolocation auth status: ' + status.authorization);

      // you don't need to check status before start (this is just the example)
      if (!status.isRunning) {
        BackgroundGeolocation.start(); //triggers start on start event
      }
    });

现在,我真的不明白为什么没有只返回状态的函数,但无论如何,我需要这样一个函数,尝试如下。

export function isBackgroundTracking() {

  // Null means undetermined, but should never be returned that way.
  var result = null;

  // This is accurately logged first.
  console.log('One');

  // This should finish before moving on.
  BackgroundGeolocation.checkStatus(status => {
    result = status.isRunning;
    // This is inaccurately logged third.
    console.log('Two:', result);
  });

  // This is inaccurately logged second.
  console.log('Three:', result);

  // This is inaccurately returned as null, because `checkStatus` is apparently asynced.
  return result;

}

在界面代码中,按钮调用函数是这样的:

<CtaButton
  bgColor={Colors.backgroundAlt}
  onPress={() => {
    stopBackgroundTracking();
    let result = isBackgroundTracking();
    console.log('Result:', result);
  }}
>

运行这段代码,输出是这样的:

 LOG  One
 LOG  Three: null
 LOG  Result: null
 LOG  Two: false

我也尝试过使用 async/await,如下所示:

export async function isBackgroundTracking() {

  // Null means undetermined, but should never be returned that way.
  var result = null;

  // This is accurately logged first.
  console.log('One');

  // This should finish before moving on.
  await BackgroundGeolocation.checkStatus(status => {
    result = status.isRunning;
    // This is inaccurately logged third.
    console.log('Two:', result);
  });

  // This is inaccurately logged second.
  console.log('Three:', result);

  // This is inaccurately returned as null, because `checkStatus` is apparently asynced.
  return result;

}

...和...

<CtaButton
  bgColor={Colors.backgroundAlt}
  onPress={async () => {
    stopBackgroundTracking();
    let result = await isBackgroundTracking();
    console.log('Result:', result);
  }}
>

但结果完全一样。

按照上面的console.log 行,我怎样才能让它以正确的顺序运行?这不一定是异步的,事实上我不希望它是异步的,但我可以忍受它是异步的,只要我得到一个返回我需要的值的函数。

【问题讨论】:

  • 之所以不能同步返回状态是因为它在系统层面是异步的。系统可能会提示用户允许或禁止使用地理位置数据。为了同步返回,它必须在等待响应时冻结线程,这简直是糟糕的设计。尤其是在 Javascript 领域,因为 JS 是单线程的。

标签: javascript react-native async-await


【解决方案1】:
export async function isBackgroundTracking() {

  // Null means undetermined, but should never be returned that way.
  var result = null;

  // This is accurately logged first.
  console.log('One');

  // This should finish before moving on.
  await new Promise(res => {
    BackgroundGeolocation.checkStatus(status => {
      result = status.isRunning;
      // This is inaccurately logged third.
      console.log('Two:', result);

      // resolve the promise
      res();
    });
  });

  // This is inaccurately logged second.
  console.log('Three:', result);

  // This is inaccurately returned as null, because `checkStatus` is apparently asynced.
  return result;

}

您也可以将其提取到一个函数中以使其变得简单

const checkStatus = () => new Promise((res,rej) => BackgroundGeolocation.checkStatus(res,rej));

export async function isBackgroundTracking() {

 ...

 result = (await checkStatus()).isRunning;

 ...

}

Turning callbacks into promises

【讨论】:

  • 太好了,非常感谢!这实际上解释了很多。我接受了前一个建议,因为它看起来更整洁,但它也可以直接开箱即用。再次感谢您的快速回复!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-01
  • 2013-11-28
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
  • 2011-02-15
相关资源
最近更新 更多