Last active
August 29, 2015 14:10
-
-
Save ThomasBurleson/f769907846bd45f52da4 to your computer and use it in GitHub Desktop.
Enhanced version of `docSearcher` webWorker discussed in Pete Darwin's blog [AngularJS Docs Performance](http://www.bacondarwin.co.uk/angularjs-docs-performance/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('search', []) | |
.service('docsSearch', ['$q','$rootScope','$timeout','NG_PAGES',BackgroundSearchService]); | |
/** | |
* Document search service that uses Web Workers to index | |
* and search in the background. | |
*/ | |
function BackgroundSearchService($q, $rootScope, $timeout, NG_PAGES) { | |
console.log('Using WebWorker Search Index'); | |
// Create persistent instance... | |
var searcher = new PageSearcher($q, $rootScope, NG_PAGES); | |
// API that is performant & logical for multiple, sequential queries | |
return function search(qry) { | |
return searcher.find(qry); | |
}; | |
/** | |
* Create a specialized webWorker to index pages | |
* and support multiple queries | |
* | |
* @returns {{find: function(query) }} | |
* @constructor | |
*/ | |
function PageSearcher() { | |
var worker = initialize('js/search-worker.js'); | |
// Publish simple API | |
return { | |
find: processQuery | |
}; | |
/** | |
* Add the query to the query queue | |
* @param qry | |
* @returns {*} | |
*/ | |
function processQuery(qry) { | |
var results = $q.defer(); | |
// Chain each search query... | |
worker.$queue = worker.$queue | |
.then(function startQuery() { | |
return postMessage(qry) | |
}) | |
.then(function onResponse(pages) { | |
results.resolve(pages); | |
}); | |
return results.promise; | |
} | |
/** | |
* Reset the worker.onmessage to send a message when it has | |
* completed a search query and the results are available | |
* | |
* @param qry | |
* @returns {*} | |
*/ | |
function postMessage(qry) { | |
var results = $q.defer(); | |
// Reset the callback... | |
worker.onmessage = function (oEvent) { | |
$rootScope.$apply(function () { | |
switch (oEvent.data.e) { | |
case 'query-ready': | |
var pages = oEvent.data.d.map(function (path) { | |
return NG_PAGES[path]; | |
}); | |
results.resolve(pages); | |
break; | |
default : | |
throw new Error("unknown error"); | |
} | |
}); | |
}; | |
worker.postMessage({q: qry}); | |
return results.promise; | |
} | |
/** | |
* Initialize a WebWorker and listen for `index-ready` to | |
* announce ready to run a query. | |
* | |
* NOTE: Decorate the worker with a special processing `query` queue | |
* | |
* @returns {Worker} | |
*/ | |
function initialize(path, failAfter) { | |
var startup = $q.defer(); | |
var timer = $timeout(function() { | |
startup.reject( "Worker(" + path + ") is not responding..." ); | |
}, failAfter || 5000, false); | |
try { | |
var worker = new Worker(path); | |
worker.$queue = startup.promise; | |
worker.onmessage = function (oEvent) { | |
switch (oEvent.data.e) { | |
case 'index-ready': | |
$timeout.cancel(timer); | |
startup.resolve(); | |
break; | |
} | |
}; | |
} catch( e ) { | |
$timeout.cancel(timer); | |
startup.reject( e.message ); | |
} | |
return worker; | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You sound just like me with the Angular Material team: