@@ -1755,6 +1755,17 @@ export type LogEntries = {
17551755 text : string [ ] ;
17561756} ;
17571757
1758+ type TrappedError = {
1759+ error : true ;
1760+ } ;
1761+
1762+ type TrappedRequest = {
1763+ error ?: false ;
1764+ jobId : string ;
1765+ onResolve : ( res : ArangojsResponse ) => void ;
1766+ onReject : ( error : any ) => void ;
1767+ } ;
1768+
17581769/**
17591770 * An object representing a single ArangoDB database. All arangojs collections,
17601771 * cursors, analyzers and so on are linked to a `Database` object.
@@ -1766,6 +1777,7 @@ export class Database {
17661777 protected _collections = new Map < string , Collection > ( ) ;
17671778 protected _graphs = new Map < string , Graph > ( ) ;
17681779 protected _views = new Map < string , View > ( ) ;
1780+ protected _trapRequest ?: ( trapped : TrappedError | TrappedRequest ) => void ;
17691781
17701782 /**
17711783 * Creates a new `Database` instance with its own connection pool.
@@ -1905,6 +1917,49 @@ export class Database {
19051917 return new Route ( this , path , headers ) ;
19061918 }
19071919
1920+ /**
1921+ * Creates an async job by executing the given callback function. The first
1922+ * database request performed by the callback will be marked for asynchronous
1923+ * execution and its result will be made available as an async job.
1924+ *
1925+ * Returns a {@link Job} instance that can be used to retrieve the result
1926+ * of the callback function once the request has been executed.
1927+ *
1928+ * @param callback - Callback function to execute as an async job.
1929+ *
1930+ * @example
1931+ * ```js
1932+ * const db = new Database();
1933+ * const job = await db.createJob(() => db.collections());
1934+ * while (!job.isLoaded) {
1935+ * await timeout(1000);
1936+ * await job.load();
1937+ * }
1938+ * // job.result is a list of Collection instances
1939+ * ```
1940+ */
1941+ async createJob < T > ( callback : ( ) => Promise < T > ) : Promise < Job < T > > {
1942+ const trap = new Promise < TrappedError | TrappedRequest > ( ( resolveTrap ) => {
1943+ this . _trapRequest = ( trapped ) => resolveTrap ( trapped ) ;
1944+ } ) ;
1945+ const eventualResult = callback ( ) ;
1946+ const trapped = await trap ;
1947+ if ( trapped . error ) return eventualResult as Promise < any > ;
1948+ const { jobId, onResolve, onReject } = trapped as TrappedRequest ;
1949+ return new Job (
1950+ this ,
1951+ jobId ,
1952+ ( res ) => {
1953+ onResolve ( res ) ;
1954+ return eventualResult ;
1955+ } ,
1956+ ( e ) => {
1957+ onReject ( e ) ;
1958+ return eventualResult ;
1959+ }
1960+ ) ;
1961+ }
1962+
19081963 /**
19091964 * @internal
19101965 *
@@ -1918,7 +1973,7 @@ export class Database {
19181973 * @param transform - An optional function to transform the low-level
19191974 * response object to a more useful return value.
19201975 */
1921- request < T = any > (
1976+ async request < T = any > (
19221977 options : RequestOptions & { absolutePath ?: boolean } ,
19231978 transform ?: ( res : ArangojsResponse ) => T
19241979 ) : Promise < T > ;
@@ -1934,11 +1989,11 @@ export class Database {
19341989 * @param transform - If set to `false`, the raw response object will be
19351990 * returned.
19361991 */
1937- request (
1992+ async request (
19381993 options : RequestOptions & { absolutePath ?: boolean } ,
19391994 transform : false
19401995 ) : Promise < ArangojsResponse > ;
1941- request < T = any > (
1996+ async request < T = any > (
19421997 {
19431998 absolutePath = false ,
19441999 basePath,
@@ -1949,6 +2004,35 @@ export class Database {
19492004 if ( ! absolutePath ) {
19502005 basePath = `/_db/${ encodeURIComponent ( this . _name ) } ${ basePath || "" } ` ;
19512006 }
2007+ if ( this . _trapRequest ) {
2008+ const trap = this . _trapRequest ;
2009+ this . _trapRequest = undefined ;
2010+ return new Promise < T > ( async ( resolveRequest , rejectRequest ) => {
2011+ const options = { ...opts } ;
2012+ options . headers = { ...options . headers , "x-arango-async" : "store" } ;
2013+ let jobRes : ArangojsResponse ;
2014+ try {
2015+ jobRes = await this . _connection . request ( { basePath, ...options } ) ;
2016+ } catch ( e ) {
2017+ trap ( { error : true } ) ;
2018+ rejectRequest ( e ) ;
2019+ return ;
2020+ }
2021+ const jobId = jobRes . headers [ "x-arango-async-id" ] as string ;
2022+ trap ( {
2023+ jobId,
2024+ onResolve : ( res ) => {
2025+ const result = transform ? transform ( res ) : ( res as T ) ;
2026+ resolveRequest ( result ) ;
2027+ return result ;
2028+ } ,
2029+ onReject : ( err ) => {
2030+ rejectRequest ( err ) ;
2031+ throw err ;
2032+ } ,
2033+ } ) ;
2034+ } ) ;
2035+ }
19522036 return this . _connection . request (
19532037 { basePath, ...opts } ,
19542038 transform || undefined
0 commit comments