简体   繁体   English

如何确定承诺结果的优先级?

[英]how to prioritize promise results?

I am working on a react app. 我正在开发一个React应用。 I need to update the state with results from api request.Now the app functions such that I have to make api requests frequently. 我需要使用api请求的结果更新状态。现在,应用程序功能使我不得不频繁发出api请求。 Therefore I set the state in then() once the results arrive. 因此,一旦结果到达,我便在then()中设置状态。 But some results take more time than others. 但是某些结果比其他结果花费更多的时间。 So sometimes the result of the previous promise sets the state rather than the current. 因此,有时先前承诺的结果将设置状态而不是当前状态。 How do I prioritize the promises such that the latest request results sets the state. 我如何确定承诺的优先级,以使最新请求结果设置状态。 Or is there another way to get rid of the previous promises once I make a call to a new one? 或者,一旦我打电话给新的诺言,还有另一种方法摆脱先前的诺言吗?

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

      });
}

The way I usually handle this is by having a instance property or similar variable that the asynchronous callback can check to see whether its results are still desired or the request is stale. 我通常通过使用实例属性或类似的变量来处理此问题,异步回调可以检查该实例属性以查看其结果是否仍然需要或请求是否过时。 For instance, in your constructor: 例如,在您的构造函数中:

this.ajaxSequence = 0;

Then making your request: 然后提出您的要求:

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...*/);

It doesn't have to be a number. 它不一定是数字。 For instance: 例如:

this.currentRequestPromise = null;

then 然后

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

There are many ways of doing this. 有很多方法可以做到这一点。 One way I prefer is to have an object instance (a requestSequence of sorts) that keep track of requests received, along with an incrementing index value for each. 我更喜欢的一种方法是拥有一个对象实例( requestSequence ),该实例跟踪接收到的请求以及每个请求的递增索引值。 When a request/promise returns, check if the index of that request index is >= the largestIndex you've already returned from requestSequence . 当一个请求/允诺的回报,检查是否该请求索引的索引是> =的largestIndex你已经从返回requestSequence If it is, then return that result, and increment the largestIndex . 如果是,则返回该结果,并增加largestIndex Otherwise, don't return that value. 否则,请勿返回该值。

The benefit of this approach is that the caller of this code can issue requests as fast as it wants, and requestSequence will ensure order. 这种方法的好处是,此代码的调用者可以根据需要尽快发出请求,而requestSequence将确保顺序。 The caller won't have to be concerned with expiring requests or checking if the returned value matches the current input. 调用者将不必担心过期的请求或检查返回的值是否与当前输入匹配。

You should take a look at observables for your execution flow. 您应该查看执行流程中的可观察对象。 What you are looking for is flattening non concurrently a stream of promises which can be done pretty easily with a library such as xstream : 您正在寻找的是不同时拉平承诺流,这可以通过xstream的库轻松完成:

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

Creating a stream of promises is easy, assuming you need to fetch periodically you can have 假设您需要定期获取,您可以轻松创建承诺流

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

I would strongly advise you look in this direction. 我强烈建议您朝这个方向看。 Trying to handle directly promises within you component lifecycle is not straightforward and should probably be done in a Redux middleware (or other state management utilities). 尝试直接处理组件生命周期中的promise不是一件容易的事,应该在Redux中间件(或其他状态管理实用程序)中完成。 For instance it requires you track the state of your component being mounted/unmounted inside your promise's callbacks, otherwise you might do operations on unmounted components. 例如,它要求您在Promise的回调中跟踪正在安装/卸载的组件的状态,否则您可能会对未安装的组件进行操作。 This could also lead to memory leaks. 这也可能导致内存泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM