From c9f3a12693345a5e591f6518fdabbe453096e5df Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 13 Jul 2017 16:51:14 +0100 Subject: [PATCH 1/3] Fix Autocompleter promises Use bluebird instead of the now removed "q" library. Also, make sure we timeout and then `reflect` to effectively do an `allSettled` that waits for all promises to either be resolved or rejected. Then we filter for those that are fulfilled and return the completions. --- src/autocomplete/Autocompleter.js | 44 ++++++++++++++++--------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/autocomplete/Autocompleter.js b/src/autocomplete/Autocompleter.js index 6b8cd66ae2..ec5d84f9a2 100644 --- a/src/autocomplete/Autocompleter.js +++ b/src/autocomplete/Autocompleter.js @@ -52,28 +52,30 @@ export async function getCompletions(query: string, selection: SelectionRange, f otherwise, we run into a condition where new completions are displayed while the user is interacting with the list, which makes it difficult to predict whether an action will actually do what is intended - - It ends up containing a list of Q promise states, which are objects with - state (== "fulfilled" || "rejected") and value. */ - const completionsList = await Q.allSettled( - PROVIDERS.map(provider => { - return Promise.resolve(provider.getCompletions(query, selection, force)) - .timeout(PROVIDER_COMPLETION_TIMEOUT); - }), + */ + const completionsList = await Promise.all( + // Array of inspections of promises that might timeout. Instead of allowing a + // single timeout to reject the Promise.all, reflect each one and once they've all + // settled, filter for the fulfilled ones + PROVIDERS.map((provider) => { + // Convert to bluebird promise so that we can do a timeout + const p = Promise.resolve(provider.getCompletions(query, selection, force)); + return p.timeout(PROVIDER_COMPLETION_TIMEOUT); + }).map((p) => p.reflect()), ); - return completionsList - .filter(completion => completion.state === "fulfilled") - .map((completionsState, i) => { - return { - completions: completionsState.value, - provider: PROVIDERS[i], + return completionsList.filter( + (inspection) => inspection.isFulfilled(), + ).map((completionsState, i) => { + return { + completions: completionsState.value(), + provider: PROVIDERS[i], - /* the currently matched "command" the completer tried to complete - * we pass this through so that Autocomplete can figure out when to - * re-show itself once hidden. - */ - command: PROVIDERS[i].getCurrentCommand(query, selection, force), - }; - }); + /* the currently matched "command" the completer tried to complete + * we pass this through so that Autocomplete can figure out when to + * re-show itself once hidden. + */ + command: PROVIDERS[i].getCurrentCommand(query, selection, force), + }; + }); } From f78a49b3a9489f7c21889af72c077f7b12f17472 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 13 Jul 2017 17:20:17 +0100 Subject: [PATCH 2/3] Do `reflect` in the same `map` --- src/autocomplete/Autocompleter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/autocomplete/Autocompleter.js b/src/autocomplete/Autocompleter.js index ec5d84f9a2..8d78aa448a 100644 --- a/src/autocomplete/Autocompleter.js +++ b/src/autocomplete/Autocompleter.js @@ -60,8 +60,8 @@ export async function getCompletions(query: string, selection: SelectionRange, f PROVIDERS.map((provider) => { // Convert to bluebird promise so that we can do a timeout const p = Promise.resolve(provider.getCompletions(query, selection, force)); - return p.timeout(PROVIDER_COMPLETION_TIMEOUT); - }).map((p) => p.reflect()), + return p.timeout(PROVIDER_COMPLETION_TIMEOUT).reflect(); + }), ); return completionsList.filter( From dcc4db53f9feade28736d6334c6f91fa955ad9eb Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 13 Jul 2017 17:51:14 +0100 Subject: [PATCH 3/3] Async functions now return `bluebird` promises, remove redundant Promise.resolve --- src/autocomplete/Autocompleter.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/autocomplete/Autocompleter.js b/src/autocomplete/Autocompleter.js index 8d78aa448a..e47c5dd59c 100644 --- a/src/autocomplete/Autocompleter.js +++ b/src/autocomplete/Autocompleter.js @@ -58,9 +58,10 @@ export async function getCompletions(query: string, selection: SelectionRange, f // single timeout to reject the Promise.all, reflect each one and once they've all // settled, filter for the fulfilled ones PROVIDERS.map((provider) => { - // Convert to bluebird promise so that we can do a timeout - const p = Promise.resolve(provider.getCompletions(query, selection, force)); - return p.timeout(PROVIDER_COMPLETION_TIMEOUT).reflect(); + return provider + .getCompletions(query, selection, force) + .timeout(PROVIDER_COMPLETION_TIMEOUT) + .reflect(); }), );