【问题标题】:how to prioritize promise results?如何优先考虑承诺结果?
【发布时间】:2018-11-25 12:02:29
【问题描述】:

我正在开发一个反应应用程序。我需要使用 api 请求的结果来更新状态。现在应用程序运行起来,我必须经常发出 api 请求。因此,一旦结果到达,我就在 then() 中设置状态。但有些结果比其他结果需要更多时间。所以有时前一个承诺的结果会设置状态而不是当前。我如何确定承诺的优先级,以便最新的请求结果设置状态。或者,一旦我打电话给新的承诺,还有其他方法可以摆脱以前的承诺吗?

this.state = {
      searchterm: '',
      isfocused: false,
      current: -1,
      noresults: false,
      // latest promise id
      reqseqid: 0,
      filteredList: []
    }


callingfunction(){
   let reqseqid = this.state.reqseqid + 1;
    this.setState({ 
      searchterm,
      filteredList: [],
      reqseqid
     });
    searchresults(searchterm, reqseqid)
      .then(res => {
        let { results, reqseqid } = res;
        console.log(reqseqid, this.state.reqseqid);
        if(reqseqid === this.state.reqseqid){
          if(res.length === 0){
            this.setState({ 
              current: -1,
              filteredList: [],
              noresults: true
             });
          }else{
            this.setState({ 
              current: -1,
              filteredList: results,
              noresults: false
            });
          }
        }

      });
}

【问题讨论】:

    标签: javascript reactjs asynchronous promise state


    【解决方案1】:

    我通常处理这个问题的方法是使用一个实例属性或类似的变量,异步回调可以检查它的结果是否仍然需要或请求是否过时。例如,在您的构造函数中:

    this.ajaxSequence = 0;
    

    然后提出您的要求:

    const thisSequence = ++this.ajaxSequence;
    doTheAjaxRequest()
        .then(result => {
            if (thisSequence == this.ajaxSequence) {
                // Use the result
            }
        })
        .catch(/*...probably check and ignore the error if this request was stale...*/);
    

    不一定是数字。例如:

    this.currentRequestPromise = null;
    

    然后

    const thisPromise = this.currentRequestPromise = doTheAjaxRequest()
        .then(result => {
            if (thisPromise == this.currentRequestPromise) {
                // Use the result
            }
        })
        .catch(/*...probably check here too...*/);
    

    【讨论】:

      【解决方案2】:

      您应该查看执行流程的 observables。您正在寻找的是非同时展平一个承诺流,这可以通过 xstream 之类的库轻松完成:

      const xs = require("xstream").default;
      const promise$ = ... // create a stream of promises
      return promise$.map(p => xs.fromPromise(p)).flatten();
      

      创建一个 Promise 流很容易,假设您需要定期获取,您可以拥有

      const promise$ = xs.periodic(500).map(() => makeApiCall());
      

      我强烈建议您朝这个方向看。尝试在组件生命周期中直接处理 Promise 并不简单,可能应该在 Redux 中间件(或其他状态管理实用程序)中完成。例如,它要求您在 Promise 的回调中跟踪组件的挂载/卸载状态,否则您可能会对未挂载的组件进行操作。这也可能导致内存泄漏。

      【讨论】:

      • 这会导致对已知过时的完成进行不必要的组件状态更新,不是吗?因为您按照结果开始的顺序处理结果,即使后面的结果在前面的结果之前完成,所以不再需要前面的结果。
      • 不在我发布的内容中。每次新的 Promise 到达时,前一个 Promise 都会被丢弃。
      • 好的,很酷,谢谢。如果其他人也有同样的疑问,我会留下评论。
      • 您描述的是流连接,您在处理下一个之前等待一个完成。我建议的是扁平化,这是不同的。非并发时,它会在新的流出现时丢弃当前流,同时它会尽可能多地打开订阅。
      【解决方案3】:

      有很多方法可以做到这一点。我喜欢的一种方法是拥有一个对象实例(requestSequence of sorts)来跟踪收到的请求,以及每个请求的递增索引值。当请求/承诺返回时,检查该请求索引的索引是否 >= 您已经从 requestSequence 返回的 largestIndex。如果是,则返回该结果,并增加largestIndex。否则,不要返回该值。

      这种方法的好处是这段代码的调用者可以随心所欲地发出请求,requestSequence 将确保顺序。调用者不必关心过期请求或检查返回值是否与当前输入匹配。

      【讨论】:

      • 我确实尝试过类似的方法。所以请求序列只是不断增加。对吗?
      • 是的。它可能是您递增的整数,也可能是时间戳(除非您的请求出现的频率高于每毫秒一次)。详情:requestSequence 是一个实例,它在实例内存储一个索引(避免全局状态)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多