diff --git a/samples/react/MusicStore/ReactApp/fx/domain-tasks.ts b/samples/react/MusicStore/ReactApp/fx/domain-tasks.ts deleted file mode 100644 index 927895a..0000000 --- a/samples/react/MusicStore/ReactApp/fx/domain-tasks.ts +++ /dev/null @@ -1,49 +0,0 @@ -const domain = require('domain') as any; -const domainContext = require('domain-context') as any; -const domainTasksStateKey = '__DOMAIN_TASKS'; - -export function addTask(task: PromiseLike) { - if (task && domain.active) { - const state = domainContext.get(domainTasksStateKey) as DomainTasksState; - if (state) { - state.numRemainingTasks++; - task.then(() => { - // The application may have other listeners chained to this promise *after* - // this listener. Since we don't want the combined task to complete until - // all the handlers for child tasks have finished, delay the following by - // one tick. - setTimeout(() => { - state.numRemainingTasks--; - if (state.numRemainingTasks === 0) { - state.triggerResolved(); - } - }, 0); - }, state.triggerRejected); - } - } -} - -export function run(codeToRun: () => void): Promise { - return new Promise((resolve, reject) => { - domainContext.runInNewDomain(() => { - const state: DomainTasksState = { - numRemainingTasks: 0, - triggerResolved: resolve, - triggerRejected: reject - }; - domainContext.set(domainTasksStateKey, state); - codeToRun(); - - // If no tasks were registered synchronously, then we're done already - if (state.numRemainingTasks === 0) { - resolve(); - } - }); - }) as any as Promise; -} - -interface DomainTasksState { - numRemainingTasks: number; - triggerResolved: () => void; - triggerRejected: () => void; -} diff --git a/samples/react/MusicStore/ReactApp/fx/isomorphic-fetch.d.ts b/samples/react/MusicStore/ReactApp/fx/isomorphic-fetch.d.ts deleted file mode 100644 index a280907..0000000 --- a/samples/react/MusicStore/ReactApp/fx/isomorphic-fetch.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare module 'isomorphic-fetch' { - export default function fetch(url: string, opts: any): Promise; -} diff --git a/samples/react/MusicStore/ReactApp/fx/render-server.js b/samples/react/MusicStore/ReactApp/fx/render-server.js index 7299c68..ed90735 100644 --- a/samples/react/MusicStore/ReactApp/fx/render-server.js +++ b/samples/react/MusicStore/ReactApp/fx/render-server.js @@ -1,8 +1,9 @@ require('./require-ts-babel')(); // Enable loading TS/TSX/JSX/ES2015 modules var url = require('url'); -var domainTasks = require('./domain-tasks.ts'); +var domainTasks = require('domain-tasks'); +var baseUrl = require('domain-tasks/fetch').baseUrl; -function render(bootModulePath, requestUrl, callback) { +function render(bootModulePath, absoluteRequestUrl, requestPathAndQuery, callback) { var bootFunc = require(bootModulePath); if (typeof bootFunc !== 'function') { bootFunc = bootFunc.default; @@ -12,13 +13,15 @@ function render(bootModulePath, requestUrl, callback) { } var params = { - location: url.parse(requestUrl), - url: requestUrl, + location: url.parse(requestPathAndQuery), + url: requestPathAndQuery, state: undefined }; // Open a new domain that can track all the async tasks commenced during first render domainTasks.run(function() { + baseUrl(absoluteRequestUrl); + // Since route matching is asynchronous, add the rendering itself to the list of tasks we're awaiting domainTasks.addTask(new Promise(function (resolve, reject) { // Now actually perform the first render that will match a route and commence associated tasks @@ -33,19 +36,16 @@ function render(bootModulePath, requestUrl, callback) { } }); })); - }).then(function() { + }, function(error) { // By now, all the data should be loaded, so we can render for real based on the state now // TODO: Add an optimisation where, if domain-tasks had no outstanding tasks at the end of // the previous render, we don't re-render (we can use the previous html and state). + if (error) { console.error(error); throw error; } bootFunc(params, callback); - }).catch(function(error) { - process.nextTick(() => { // Because otherwise you can't throw from inside a catch - callback(error, null); - }); }); } -render('../boot-server.tsx', '/', (err, html) => { +render('../boot-server.tsx', 'http://localhost:5000', '/', (err, html) => { if (err) { throw err; } diff --git a/samples/react/MusicStore/ReactApp/fx/tracked-fetch.ts b/samples/react/MusicStore/ReactApp/fx/tracked-fetch.ts deleted file mode 100644 index 80795d6..0000000 --- a/samples/react/MusicStore/ReactApp/fx/tracked-fetch.ts +++ /dev/null @@ -1,13 +0,0 @@ -import isomorphicFetch from 'isomorphic-fetch'; -import { addTask } from './domain-tasks'; - -export function fetch(url: string): Promise { - // TODO: Find some way to supply the base URL via domain context - var promise = isomorphicFetch('http://localhost:5000' + url, { - headers: { - Connection: 'keep-alive' - } - }); - addTask(promise); - return promise; -} diff --git a/samples/react/MusicStore/ReactApp/store/AlbumDetails.ts b/samples/react/MusicStore/ReactApp/store/AlbumDetails.ts index 2e10f5b..eff9796 100644 --- a/samples/react/MusicStore/ReactApp/store/AlbumDetails.ts +++ b/samples/react/MusicStore/ReactApp/store/AlbumDetails.ts @@ -1,4 +1,4 @@ -import { fetch } from '../fx/tracked-fetch'; +import { fetch } from 'domain-tasks/fetch'; import { typeName, isActionType, Action, Reducer } from '../fx/TypedRedux'; import { ActionCreator } from './'; import { Genre } from './GenreList'; diff --git a/samples/react/MusicStore/ReactApp/store/FeaturedAlbums.ts b/samples/react/MusicStore/ReactApp/store/FeaturedAlbums.ts index a2a3ebd..5a4bb9c 100644 --- a/samples/react/MusicStore/ReactApp/store/FeaturedAlbums.ts +++ b/samples/react/MusicStore/ReactApp/store/FeaturedAlbums.ts @@ -1,4 +1,4 @@ -import { fetch } from '../fx/tracked-fetch'; +import { fetch } from 'domain-tasks/fetch'; import { typeName, isActionType, Action, Reducer } from '../fx/TypedRedux'; import { ActionCreator } from './'; diff --git a/samples/react/MusicStore/ReactApp/store/GenreDetails.ts b/samples/react/MusicStore/ReactApp/store/GenreDetails.ts index d6f3ef0..c47fba6 100644 --- a/samples/react/MusicStore/ReactApp/store/GenreDetails.ts +++ b/samples/react/MusicStore/ReactApp/store/GenreDetails.ts @@ -1,4 +1,4 @@ -import { fetch } from '../fx/tracked-fetch'; +import { fetch } from 'domain-tasks/fetch'; import { typeName, isActionType, Action, Reducer } from '../fx/TypedRedux'; import { ActionCreator } from './'; import { Album } from './FeaturedAlbums'; diff --git a/samples/react/MusicStore/ReactApp/store/GenreList.ts b/samples/react/MusicStore/ReactApp/store/GenreList.ts index 2742e2b..682bded 100644 --- a/samples/react/MusicStore/ReactApp/store/GenreList.ts +++ b/samples/react/MusicStore/ReactApp/store/GenreList.ts @@ -1,4 +1,4 @@ -import { fetch } from '../fx/tracked-fetch'; +import { fetch } from 'domain-tasks/fetch'; import { typeName, isActionType, Action, Reducer } from '../fx/TypedRedux'; import { ActionCreator } from './'; diff --git a/samples/react/MusicStore/package.json b/samples/react/MusicStore/package.json index c56e854..16ba485 100644 --- a/samples/react/MusicStore/package.json +++ b/samples/react/MusicStore/package.json @@ -21,6 +21,7 @@ "dependencies": { "bootstrap": "^3.3.6", "domain-context": "^0.5.1", + "domain-tasks": "^1.0.0", "isomorphic-fetch": "^2.2.1", "ntypescript": "^1.201602072208.1", "react": "^0.14.7",