1
- import type { AxiosResponse } from 'axios' ;
1
+ import type { AxiosResponse , CancelTokenSource } from 'axios' ;
2
2
import axios from 'axios' ;
3
3
import { default as xss } from 'xss' ;
4
4
import type {
@@ -35,6 +35,7 @@ const FEEDBACK_COMMENT = `dtp/api/${VERSION}/feedback/comment`;
35
35
const FEEDBACK_OUTCOME = `dtp/api/${ VERSION } /feedback/outcome` ;
36
36
const DEFAULT_MAX_RESULTS = 9999 ;
37
37
38
+ const previousToken : CancelTokenSource [ ] = [ ] ;
38
39
/**
39
40
* Returns API to programmatically access Guided Answers.
40
41
*
@@ -53,7 +54,7 @@ export function getGuidedAnswerApi(options?: APIOptions): GuidedAnswerAPI {
53
54
enhanceNode ( { node : await getNodeById ( apiHost , id ) , extensions, logger, ide } ) ,
54
55
getTreeById : async ( id : GuidedAnswerTreeId ) : Promise < GuidedAnswerTree > => getTreeById ( apiHost , id ) ,
55
56
getTrees : async ( queryOptions ?: GuidedAnswersQueryOptions ) : Promise < GuidedAnswerTreeSearchResult > =>
56
- getTrees ( apiHost , queryOptions ) ,
57
+ getTrees ( apiHost , logger , queryOptions ) ,
57
58
getNodePath : async ( nodeIdPath : GuidedAnswerNodeId [ ] ) : Promise < GuidedAnswerNode [ ] > => {
58
59
let nodes = await getNodePath ( apiHost , nodeIdPath ) ;
59
60
nodes = nodes . map ( ( node ) => enhanceNode ( { node, extensions, logger, ide } ) ) ;
@@ -156,13 +157,19 @@ async function getTreeById(host: string, id: GuidedAnswerTreeId): Promise<Guided
156
157
}
157
158
158
159
/**
159
- * Returns an array of Guided Answers trees .
160
+ * Fetches guided answer trees based on the provided query options .
160
161
*
161
- * @param host - Guided Answer API host
162
- * @param queryOptions - options like query string, filters
163
- * @returns - Array of Guided Answer trees
162
+ * @param {string } host - The host URL for the API.
163
+ * @param {Logger } logger - The logger instance for logging debug information.
164
+ * @param {GuidedAnswersQueryOptions } [queryOptions] - Optional query options including filters and paging.
165
+ * @returns {Promise<GuidedAnswerTreeSearchResult> } A promise that resolves to the search result containing guided answer trees.
166
+ * @throws {Error } Throws an error if the query is a number or if the response does not contain a 'trees' array.
164
167
*/
165
- async function getTrees ( host : string , queryOptions ?: GuidedAnswersQueryOptions ) : Promise < GuidedAnswerTreeSearchResult > {
168
+ async function getTrees (
169
+ host : string ,
170
+ logger : Logger ,
171
+ queryOptions ?: GuidedAnswersQueryOptions
172
+ ) : Promise < GuidedAnswerTreeSearchResult > {
166
173
if ( typeof queryOptions ?. query === 'number' ) {
167
174
throw Error (
168
175
`Invalid search for tree with number. Please use string or function getTreeById() to get a tree by id`
@@ -171,13 +178,40 @@ async function getTrees(host: string, queryOptions?: GuidedAnswersQueryOptions):
171
178
const query = queryOptions ?. query ? encodeURIComponent ( `"${ queryOptions . query } "` ) : '*' ;
172
179
const urlGetParamString = convertQueryOptionsToGetParams ( queryOptions ?. filters , queryOptions ?. paging ) ;
173
180
const url = `${ host } ${ TREE_PATH } ${ query } ${ urlGetParamString } ` ;
174
- const response : AxiosResponse < GuidedAnswerTreeSearchResult > = await axios . get < GuidedAnswerTreeSearchResult > ( url ) ;
175
- const searchResult = response . data ;
176
- if ( ! Array . isArray ( searchResult ?. trees ) ) {
177
- throw Error (
178
- `Query result from call '${ url } ' does not contain property 'trees' as array. Received response: '${ searchResult } '`
179
- ) ;
181
+
182
+ // Cancel the previous request if it exists
183
+ if ( previousToken . length ) {
184
+ const prev = previousToken . pop ( ) ;
185
+ prev ?. cancel ( 'Canceling previous request' ) ;
186
+ }
187
+
188
+ // Create a new CancelToken for the current request
189
+ const source = axios . CancelToken . source ( ) ;
190
+ previousToken . push ( source ) ;
191
+
192
+ let searchResult : GuidedAnswerTreeSearchResult = {
193
+ resultSize : - 1 ,
194
+ trees : [ ] ,
195
+ productFilters : [ ] ,
196
+ componentFilters : [ ]
197
+ } ;
198
+
199
+ try {
200
+ const response = await axios . get < GuidedAnswerTreeSearchResult > ( url , {
201
+ cancelToken : source . token
202
+ } ) ;
203
+ searchResult = response . data ;
204
+ if ( ! Array . isArray ( searchResult ?. trees ) ) {
205
+ throw Error ( `Query result from call '${ url } ' does not contain property 'trees' as array` ) ;
206
+ }
207
+ } catch ( error ) {
208
+ if ( axios . isCancel ( error ) ) {
209
+ logger . logDebug ( `Request canceled: '${ error . message } '` ) ;
210
+ } else {
211
+ throw error ;
212
+ }
180
213
}
214
+
181
215
return searchResult ;
182
216
}
183
217
0 commit comments