Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在then()内获得对当前承诺的引用_Javascript_Promise_Cancellation - Fatal编程技术网

Javascript 如何在then()内获得对当前承诺的引用

Javascript 如何在then()内获得对当前承诺的引用,javascript,promise,cancellation,Javascript,Promise,Cancellation,在下面的代码中,我想检查回调是否从latestRequest执行,因此我正在检查thisPromise,以查看它是否与latestRequest相同。显然,这个承诺不起作用。有没有办法得到目前的承诺 let latestRequest = MyLib .retrieve(getFilteredQuery(filters, queries, user)) .then(res => { // Checking whether this is the latest request

在下面的代码中,我想检查回调是否从latestRequest执行,因此我正在检查
thisPromise
,以查看它是否与
latestRequest
相同。显然,这个承诺不起作用。有没有办法得到目前的承诺

let latestRequest = MyLib
  .retrieve(getFilteredQuery(filters, queries, user))
  .then(res => {
    // Checking whether this is the latest request handler
    if (latestRequest === thisPromise) {
      updateData(res)
    }
  })
  .catch(err => {
    console.error(err)
  })

我的用例用于处理来自API的请求。我只想更新最新请求的数据。请求可能需要非常不同的时间返回,有时较早的请求稍后返回并覆盖最新的请求。如果您知道处理此问题的好方法,请告诉我。

没有获取对承诺对象的引用的方法
。然后从
提供的处理程序中调用了
。然后

一个建议是为处理程序分配一个序列号,并检查它是否是从闭包中发出的最后一个序列号。未经测试的示例:

let latestRequestId = 0;

let checkLatest = ()=> {
    let thisRequest = ++latestRequestId;
    return (res=>{
    // Checking whether this is the latest request handler
    if (latestRequestId === thisRequest) {
      updateData(res)
    }
  })
}

let latestRequest = MyLib
  .retrieve(getFilteredQuery(filters, queries, user))
  .then(checkLatest())
  .catch(err => {
    console.error(err)
  })

关闭内的实施:

const run = (() => {
  let currentPromise;

  return () => {
    const p = new Promise((resolve, reject) => {
      // run an asynchronous process and resolve like resolve(results)
    })
    .then(results => {
      if (p === currentPromise) {
        // process results here
      }
    })

    currentPromise = p;
  }
})()
使用
的类似替代方案:

class Request {
  static #currentPromise;

  static run() {
    const p = new Promise((resolve, reject) => {
      // run an asynchronous process and resolve like resolve(results)
    })
    .then(results => {
      if (p === Request.#currentPromise) {
        // process results here
      }
    })

    Request.#currentPromise = p;
  }
}
您可以通过使用模拟延迟实现来进行测试:

const run = (() => {
  let currentPromise;

  return (timeout) => {
    const p = new Promise((resolve, reject) => {
      setTimeout(_ => resolve(timeout), timeout);
    })
    .then(data => {
      if (p === currentPromise) {
        console.log('latest request', data);
      }
    })

    currentPromise = p;
  }
})()

run(1000); // 1s request
run( 500);
run(  10); // last request, 0.1s

我建议只为每个请求分配一个计数器(在请求范围内的某个地方),并跟踪您从中获得结果的最高计数器,然后您可以忽略任何迟到的旧请求(较低的计数器值)。这似乎也比试图比较承诺要防弹得多。请记住,承诺链由多个承诺组成,因为每次调用
newpromise()
。然后()
创建一个新承诺。这不仅仅是一条链条中的一个承诺。您显示的代码中有多个活动承诺。您的代码中只有一个
latestPromise
。请展示创建多个承诺的完整代码。@Bergi我已经包括了简化的示例代码。将该代码视为在一个可以从应用程序中的其他位置调用的函数中。那么,只需保留一个全局
latestPromise
和多个本地
thisPromise
变量。您在ThereThreak@Bergi中有两个
latestRequest
变量,已修复:)如果只有静态属性,请不要使用
class
语法
class
如果需要,可以使用私有属性进行封装。一个简单的iLife或一个模块作用域也可以做到这一点。无需滥用
语法作为命名空间。