2015-08-25 13 views
6

Sto lavorando con un sito Web pesante e ho bisogno di supportare IE8. Sto riscontrando alcuni errori di "slow-running script" in IE8, quindi sto adattando il mio codice in pausa periodicamente durante i loop per i browser più vecchi.JavaScript: Adattare il codice sincrono per essere asincrono, per supportare IE8?

Questo è il mio codice corrente:

combineData: function(xData, yData, values) { 
    var combinedData = this.combineDatasets(xData, yData, values.x, values.x_val); 
    combinedData = this.calculateRatiosForData(combinedData); 
    // various other data operations, then continue to set up chart... 
}, 

calculateRatiosForData: function(data, isSpecialDenominator, x_val_key) { 
    _.each(data, function(d, i) { 
     // do some calculations... 
    }); 
    return data; 
}, 

Come posso adattarmi calculateRatiosForData per elaborare N righe alla volta, poi una pausa?

Questo lo renderà asincrono e sto cercando di adattare il mio codice per gestirlo.

Ovviamente tutto ciò che faccio deve essere supportato in IE8!

+0

Ho letto http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call?rq=1 ma sto davvero lottando per capire come per adattarlo al mio codice esistente. Ho un sacco di funzioni sincrone al di fuori di 'combineData', ho davvero bisogno di cambiarle tutte per essere asincrone? – Richard

+0

c'è un modo per eseguire i rapporti di calcolo sul server? – RadleyMith

+0

Dai un'occhiata a http://stackoverflow.com/q/6864397/1048572, http://stackoverflow.com/q/714942/1048572. E sì, dovrai cambiare tutto ciò che dipende dai risultati di ciò per gestire asincroni. – Bergi

risposta

5

Direi di unire i dati in N righe prima di entrare in rapporti di calcolo. Rendere i rapporti di calcolo una singola funzione cioè. questa parte del programma // do some calculations... lo promette utilizzando Q.

Dopo di che è possibile creare una serie di promesse ogni promessa è calculateRatiosForData(Nth row).

Successivamente è possibile effettuare una chiamata a Promise.all(yourArrayOfCalculateRatioPromises).

Il problema è che continuerai a calcolare tutti i dati sul browser. Se possibile, sarebbe meglio scaricare tale elaborazione sul server e utilizzare una richiesta POST per l'elaborazione. La struttura delle promesse sembrerà sempre la stessa.

C'è anche il problema di decidere se sono necessari questi valori calcolati per il resto del copione. Se non sei bravo, se lo fai, incapsuleresti il ​​resto dello script all'interno dello Promise.all(arrayOfPromises).then(function (result) { //rest of script}. Il pezzo chiave di quel codice è lo .then (function() {}).

Suggerisco di utilizzare WebWorkers ma purtroppo non sono supportati da IE8. Ci sono soluzioni alternative trovate in google code e anche here ma non posso garantire per quanto bene funzioneranno queste opzioni.

EDIT: questo mostrerà come fare la promessa

Ci sono fondamentalmente due modi per farlo.

1) È possibile scrivere la funzione calculateRatios nello stile di un nodo indietro e poi promisify utilizzando D.

function calculateRatios (arrayInput, callback) { 
    //error checking if error 
    //callback(error) 

    //calculate the ratios algorithm then do 
    setTimeout(callback(undefined, data), 500); 
} 

E poi a promisify sarebbe simile a questa:

var Promise = require('q'), //however you want to do this in the browser 
    calculateRatiosAsync = Promise.promisify(calculateRatios); 

Personalmente mi piace in questo modo perché è compatibile con altre librerie di controllo di flusso senza dover modificare la funzione originale, oppure puoi semplicemente usare la funzione originale nel modo in cui lo hai, se non è necessario prometterlo.

2) L'altro modo è creare esplicitamente una promessa.

var Promise = require('q'), 
    calculateRaiosAsync = function (input) { 
     var d = Promise.defer(); 

     //do your error checking if error 
     d.reject(); 

     //do your calclate ratios algorithm and store the data in a variable 
     setTimeout(d.resolve(yourFinishedData), 500); 

     //return your promise 
     return d.promise(); 
    } 

NOTA: Va notato che si dovrà richiedere la biblioteca promessa in modo diverso, ma lascio che a voi.

+0

grazie, potresti dare qualche esempio di codice? – Richard

+0

cosa vuoi un esempio di ... Ho bisogno di contesto. Vuoi vedere come creare una promessa? Vuoi vedere come fare una richiesta POST al server e usare le promesse con quello? Non è possibile effettuare una grande computazione nel brower, non un grande calcolo nel browser, a meno che non si renda l'algoritmo più efficiente o lo si scarichi sul server. – RadleyMith

+0

Grazie! Voglio letteralmente vedere come adattare 'calculateRatiosForData' in modo che calcoli 1000 righe alla volta, quindi sospenda per mezzo secondo e non ritorni finché non è finito. In un modo che funziona in IE8. Sicuramente non voglio pubblicare nulla sul server. Il grande calcolo nel browser funziona bene in tutti i browser moderni. – Richard