是否可以在 Promise 中包装诸如 Geolocation.watchPosition() 之类的函数?

Is it possible to wrap function such as Geolocation.watchPosition() in a Promise?

我想知道是否可以将 Geolocation.watchPosition() https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition 包装在一个 Promise 中,并以某种方式将其与 async/await 习语一起使用;每当设备的位置发生变化并调用后续功能时,就会不断 returns 定位。

// 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)
    }
  }
}

还没有。

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

在 ES2015 中我们得到了生成器:function* & yield,它允许 迭代器 - 用 [=15= 拉动每个 yield ]...of 循环。

Generators 还支持推送 Observers,使用 var valToGet = yield foo;generator.next(valToPush); 语法。

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

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

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

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);
    }
}

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

与此同时,有一些支持观察者模式的特殊库现在可用,例如 RxJS