diff --git a/src/JBrowse/Store/BigWig.js b/src/JBrowse/Store/BigWig.js index b79ecf4e30..fb23081f70 100644 --- a/src/JBrowse/Store/BigWig.js +++ b/src/JBrowse/Store/BigWig.js @@ -102,7 +102,7 @@ return declare( null, load: function() { var bwg = this; var headerSlice = bwg.data.slice(0, 512); - headerSlice.fetch(function(result) { + headerSlice.fetch( function(result) { if (!result) { bwg._loading.resolve({ success: false }); return; @@ -177,7 +177,9 @@ return declare( null, bwg._readChromTree(function() { bwg._loading.resolve({success: true}); }); - }); + }, + function( error ) { bwg._loading.resolve({success: false, error: error }); } + ); }, loadSuccess: function() {}, diff --git a/src/JBrowse/Store/RemoteBinaryFile.js b/src/JBrowse/Store/RemoteBinaryFile.js index 5e6440fe41..aebeb63add 100644 --- a/src/JBrowse/Store/RemoteBinaryFile.js +++ b/src/JBrowse/Store/RemoteBinaryFile.js @@ -254,10 +254,11 @@ return declare( null, }, /** - * @param args.url - * @param args.start - * @param args.end - * @param args.success + * @param args.url {String} url to fetch + * @param args.start {Number|undefined} start byte offset + * @param args.end {Number|undefined} end byte offset + * @param args.success {Function} success callback + * @param args.failure {Function} failure callback */ get: function( args ) { this._log( 'get', args.url, args.start, args.end ); @@ -267,45 +268,63 @@ return declare( null, if( start && !end ) throw "cannot specify a fetch start without a fetch end"; - this._fetchChunks( args.url, start, end, dojo.hitch( this, function( chunks ) { - this._log( 'golden path', chunks); - - var fetchLength = end ? end - start + 1 // use start end end if we have it - : Math.max.apply( Math, // otherwise calculate from the end offsets of the chunks - array.map( - chunks, - function(c) { - return c.key.end || - // and possibly calculate the end offset of the chunk from its start + its length - (c.key.start + (c.value||{}).byteLength || 0); - }) - ) + 1; - - - var returnBuffer; - - // if we just have one chunk, return either it, or a subarray of it. don't have to do any array copying - if( chunks.length == 1 && chunks[0].key.start == start && (!end || chunks[0].key.end == end) ) { - returnBuffer = chunks[0].value; - } else { - // stitch them together into one ArrayBuffer to return - returnBuffer = new Uint8Array( fetchLength ); - var cursor = 0; - array.forEach( chunks, function( chunk ) { - var b = new Uint8Array( chunk.value ); - var bOffset = (start+cursor) - chunk.key.start; if( bOffset < 0 ) this._error('chunking error'); - var length = Math.min( b.byteLength - bOffset, fetchLength - cursor ); - this._log( 'arrayCopy', b, bOffset, returnBuffer, cursor, length ); - arrayCopy( b, bOffset, returnBuffer, cursor, length ); - this._arrayCopyCount++; - cursor += length; - },this); - returnBuffer = returnBuffer.buffer; - } + this._fetchChunks( + args.url, + start, + end, + dojo.hitch( this, function( chunks ) { + try { + this._assembleChunks( start, end, args.success, args.failure, chunks ); + } catch( e ) { + ( args.failure || function(){} )(e); + } + }) + ); + }, + + _assembleChunks: function( start, end, successCallback, failureCallback, chunks ) { + this._log( 'golden path', chunks); + + var fetchLength = end ? end - start + 1 // use start end end if we have it + : Math.max.apply( Math, // otherwise calculate from the end offsets of the chunks + array.map( + chunks, + function(c) { + return c.key.end || + // and possibly calculate the end offset of the chunk from its start + its length + (c.key.start + (c.value||{}).byteLength || 0); + }) + ) + 1; + + + var returnBuffer; + + if( ! Uint8Array ) { + failureCallback( 'Browser does not support typed arrays'); + return; + } + + // if we just have one chunk, return either it, or a subarray of it. don't have to do any array copying + if( chunks.length == 1 && chunks[0].key.start == start && (!end || chunks[0].key.end == end) ) { + returnBuffer = chunks[0].value; + } else { + // stitch them together into one ArrayBuffer to return + returnBuffer = new Uint8Array( fetchLength ); + var cursor = 0; + array.forEach( chunks, function( chunk ) { + var b = new Uint8Array( chunk.value ); + var bOffset = (start+cursor) - chunk.key.start; if( bOffset < 0 ) this._error('chunking error'); + var length = Math.min( b.byteLength - bOffset, fetchLength - cursor ); + this._log( 'arrayCopy', b, bOffset, returnBuffer, cursor, length ); + arrayCopy( b, bOffset, returnBuffer, cursor, length ); + this._arrayCopyCount++; + cursor += length; + },this); + returnBuffer = returnBuffer.buffer; + } - // return the data buffer - args.success( returnBuffer ); - })); + // return the data buffer + successCallback( returnBuffer ); }, _stringToBuffer: function(result) {