Data-JPack

 view release on metacpan or  search on metacpan

share/js/02-chunkloader.js  view on Meta::CPAN

  updateStatus(message,mode){
    //console.log("UPDATE STATUS CALLED");
      let e=new CustomEvent("JPACK_STATUS",{detail: {progress: parseInt(100*this.chunksLoaded/this.chunksExpected), message:message, mode:mode}});
      window.dispatchEvent(e);

  }

	/**
	 * Load the pako.js into worker pool for delfate support
   * This is actaully prencoded (no compression) for dynamic loading
	 */
	bootstrap(){

    // Path is relative to this.buildRoot
    let name="app/jpack/boot/00000000000000000000000000000000/00000000000000000000000000000000.jpack";
    return this.queueChunkScript(name)
      .then((data)=>{
        let decoder=new TextDecoder("utf-8");
        let string=decoder.decode(data);
        return this.pool.addScriptBody(string)
        .then(()=>{
          // Unload scripts
          this.unloadScript(this.buildRoot+name);

          this.chunksLoaded++;
          this.updateStatus("Boot Complete");

          return Promise.resolve();
        });

    });
	}




	//This callback is executed from a chunk script to decode/decompress the data
	//
	decodeData(options, dataFunc){
		//console.log("decodeData script call");
    let src=options.jpack_path;
    options.jpack_path=options.jpack_path.substr(this.buildRoot.length);
		let e=this.urlMap[options.jpack_path];
		e.options=options;
		e.dataFunc=dataFunc;
		e.resolver(e);
		this._executeNext();
	}

	/*Send data to worker pool for decodeing
	 */
	_decodeChunk(e){
		switch(e.options.jpack_type){
      case "app":
			case "data":
      case "boot":
				//console.log("SENDING DATA");
        //console.log(e.dataFunc());
				return this.pool.queueFunction("decode",{options:e.options,string:e.dataFunc()},[])
				.then((res)=>{
					//res.result is the decoded chunk data to now send to channel manager
					return Promise.resolve(res.result);
				})
				break;
			default:
				break;
		}

	}
	/**
   * Queues a request to download a chunk script. As chunks are large and the
   * order is important, a limited number of chunks are downloaded at one time
	 *
   * Returns a promise when the chunkscript has been downloaded, prased and
   * decoded.  The promise resolves to an arraybuffer of the decoded data
   *
   * PATHS ARE RELATIVE TO BUILD ROOT ie this.buildRoot
   * This is to match the build output paths of the jpack files
	 */

	queueChunkScript(path){
		//Add this to the queue 
		let promise;
		let entry={path:path, dataFunc:undefined};
		entry.promise=new Promise((resolve,reject)=>{
			entry.resolver=resolve;
			entry.rejecter=reject;
		});
		this.urlQueue.push(entry);
		this.urlMap[path]=entry;
		this._executeNext();

		//This promise is resolved when the script is ready to be decoded
		//ie when the dataFunc field has been assigned
		return entry.promise
		.then((e)=>{
			//Queue the decoding into the worker pool
			//console.log("ABOUT TO _decodeChunk");
			return this._decodeChunk(e);
		});
	}

	_executeNext(){
		if(this.urlQueue.length>0){
			let e=this.urlQueue.shift()
			this._loadChunk(e); //This gives a promise but the actual loadded script calls the decode directly
		}
                /****************************************************************************************/
                /* console.log("Working limit: ", this.workingLimit,"currently working", this.working); */
                /* if((this.working<this.workingLimit) && (this.urlQueue.length>0)){                    */
                /*         console.log("EXECUTE NEXT");                                                 */
                /*         this.working++;                                                              */
                /*         let e=this.urlQueue.shift()                                                  */
                /*         this._loadChunk(e);                                                          */
                /* }                                                                                    */
                /****************************************************************************************/
	}


	/* loads the chunk. The returned promise is not used.
	 * The load is complete when the chunk calls the decodeData callback
	 */
	_loadChunk(entry){
		//Run this when a decoder is available	
    let path=this.buildRoot+entry.path;
    //console.log("_loadChunk", path);
		return new Promise((resolve,reject)=>{
			setTimeout(()=>{
				this.loadScript(path).then((e)=>{
					this.updateStatus("Loading data "+ entry.path);
					//e.parentElement.removeChild(e);
					resolve();
				})
				.catch((e)=>{
					this.updateStatus("Error data "+ entry.path);
					console.log("Caught error", entry);
					entry.rejecter("Could not load script");
				});
			},0);
		});
	}

  //Fails/ends when two items can not be loaded
	load(path, callback, multi){
		let head=path;
		let segPath;;	
		let p= Promise.resolve();
		let resolver;
		let rejecter;

		let last=new Promise((resolve, reject)=>{
			resolver=resolve;
			rejecter=reject;



( run in 1.854 second using v1.01-cache-2.11-cpan-39bf76dae61 )