简体   繁体   English

承诺2在承诺1之前解决

[英]Promise 2 resolves before the Promise 1

I am doing a search in the textfield and as I type, there is a call going to the backend after say 100ms. 我在文本字段中进行搜索,当我输入时,有一个调用在100ms之后进入后端。

For example, if we search "5041" and immediately search for "50" and again make it "5041", then there are 3 calls made to the backend. 例如,如果我们搜索“5041”并立即搜索“50”并再次将其设为“5041”,那么对后端进行3次调用。

1."5041" -> Promise 1

2."50"   -> Promise 2

3."5041" -> Promise 3

However, promise 3 (web call takes 200ms) resolves before promise 2 (web call takes 500ms) which makes the screen reflect results for promise 2 ("50") when all I have in the textfield is "5041". 但是,承诺3(网络电话需要200毫秒)在承诺2(网络电话需要500毫秒)之前解决,这使得屏幕反映了承诺2(“50”)的结果,当我在文本字段中的所有内容都是“5041”时。

I need some way to let user type in the textfield without blocking the user along with the ability to show results for only the last call. 我需要一些方法让用户输入文本字段而不会阻止用户,并且只能显示最后一次调用的结果。

This is something that can be achieved using switchMap from rxjs in an angular app. 这一点是可以用实现switchMap从rxjs以成角度的应用程序。 However I need a way to achieve the same in vanilla JS. 但是我需要一种在vanilla JS中实现相同的方法。

First you can wrap your fetchData function into a something like fetchLatestSearchResults function which notes the time when network call was made and return the latest result from all the network calls (irrespective of what data was returned from server) 首先,您可以将fetchData函数包装成fetchLatestSearchResults函数,该函数记录网络调用的时间返回所有网络调用的最新结果 (无论从服务器返回什么数据)

 const generateLatestSearchFetch = function(fetchFunc){ let mostRecentResult = null; let mostRecentResultFetchTime = Date.now(); return (...args) => { const myFetchStartTime = Date.now(); return fetchFunc(...args) .then(data => { if (myFetchStartTime > mostRecentResultFetchTime) { mostRecentResult = data; mostRecentResultFetchTime = myFetchStartTime } return mostRecentResult; }); } }; 

Use Like : 使用喜欢

fetchData = generateLatestSearchFetch(fetchData);
fetchData('10'); // resolves first and returns result for 10
fetchData('102'); // resolves third and returns result for 1024
fetchData('1024'); // resolves second and returns result for 1024

Last but not the least, use debounce more on this to optimize number of network calls made for every type event. 最后但并非最不重要的是, 在此更多地使用debounce来优化为每个类型事件进行的网络调用次数。

You need a "last" function: 你需要一个“最后”功能:

// takes a function returning a promise and only reports the last resort
function last(fn) { 
  let p;
  return function(...args) {
    let current = fn(); // call the function
    p = current; // mark it as the last call
    return p.then(result => { 
      // ask am I still the last call?
      if (p === current) return result;
      else return new Promise(() => {}); // never resolve
    });
  }
}

let onlyLastSearch = last((name) => fetch('/api?name=' + name));

onlyLastSearch('a'); // will be ignored
onlyLastSearch('b'); // will be ignored
onlyLastSearch('c'); // only relevant result

You can use observer pattern for this. 您可以使用观察者模式。

const createWrapper = (fn) => {
    let counter = 0;
    let lastFetchId = 0;
    const listeners = [];
    return {
        fetch: (str) => {
            let id = ++counter;
            fn(str).then((data) => {
                if(id > lastFetchId) {
                    listeners.forEach(fn => {
                        fn(data);
                    });
                    lastFetchId = id;
                }
            });
        },
        listen: (fn) => {
            listeners.push(fn);
            return () => {
                const index = listeners.indexOf(fn);
                listeners.splice(index, 1);
            };
        }
    }
}

const SearchWrapper = createWrapper(fetchData);

SearchWrapper.fetch('a');
SearchWrapper.fetch('b');
SearchWrapper.fetch('c');

SearchWrapper.listen((data) => {
    console.log(data);
})

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

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