【问题标题】:Is it possible to wrap function such as Geolocation.watchPosition() in a Promise?是否可以将诸如 Geolocation.watchPosition() 之类的函数包装在 Promise 中?
【发布时间】:2017-07-21 20:32:48
【问题描述】:

我想知道是否可以将 Geolocation.watchPosition() https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition 包装在 Promise 中,并将其与 async/await 习语一起使用,以使其发挥作用;每当设备的位置发生变化并调用后续函数时,都会不断返回位置。

// Example Class
class Geo {
  // Wrap in Promise
  getCurrentPosition(options) {
    return new Promise((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(resolve, reject, options)
    })
  }

  // Wrap in Promise
  watchCurrentPosition(options) {
    return new Promise((resolve, reject) => {
      navigator.geolocation.watchPosition(resolve, reject, options)
    })
  }

  // Works well.
  async currentPosition() {
    try {
      let position = await this.getCurrentPosition()
      // do something with position.     
    }
    catch (error) {
      console.log(error)
    }
  }

  // Any way...?
  async watchPosition() {
    try {
      let position = await this.watchCurrentPosition()
      // do something with position whenever location changes. 
      // Invoking recursively do the job but doesn't feel right.
      watchPosition()
    }
    catch (error) {
      console.log(error)
    }
  }
}

【问题讨论】:

  • 可以完成,但是对于需要发生一次的事情来说,promise 是理想的。监听器模型——比如 Observable——会更加明显。

标签: javascript geolocation async-await ecmascript-2017


【解决方案1】:

还没有。

您描述的模式是一个 Observable - Javascript 中没有对它的语言支持,但它即将推出。

在 ES2015 中,我们得到了生成器:function*yield,这允许 迭代器 - 使用 for...of 循环拉动每个 yield

生成器还支持推送观察者,使用var valToGet = yield foo;generator.next(valToPush); 语法。

生成器是同步的——它们只是来回传递一个线程。

在 ES2017 中,我们得到了 asyncawait - 它们在后台使用生成器将 async function 中的每个 await 转换为 yield new Promise(...async function 成为 promisesiterator

理想情况下,我们可以这样做:

async watchPosition*() {
    try {
        while(this.enabled) {
            // Loop each time navigator.geolocation.watchPosition fires success
            const position = await this.watchCurrentPosition();

            // Pass back to the listener until generator.next
            const atDestination = yield position;
            if(atDestination)
                break; // We're here, stop watching
        }
    }
    catch (error) {
        console.log(error)
    }
}

不幸的是,尚不支持async function* - 函数可以是生成器或async,但不能同时是两者。也没有像迭代器那样好的 for...of 语法,只是笨拙的 generator.next(pushValue),所以使用这个假设的方法有点难看:

async listener() { 
    const generator = Geo.watchPosition();
    let item = await generator.next(false);
    while (!item.done) {
        // Update UI
        const atDestination = areWeThereYet(item.value);
        item = await generator.next(atDestination);
    }
}

所以异步迭代器/observables 即将到来,但首先要解决的问题很多。

同时,有一些支持观察者模式的特殊库现已推出,例如RxJS

【讨论】:

    猜你喜欢
    • 2014-06-08
    • 1970-01-01
    • 2016-04-23
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    相关资源
    最近更新 更多