JavaScript: 把同步代码改成异步的,支持IE8?
JavaScript: Adapt synchronous code to be async, to support IE8?
我正在处理一个数据密集型网站,我需要支持 IE8。我在 IE8 中遇到了一些 "slow-running script" 错误,因此我正在调整我的代码以在旧浏览器的循环期间定期暂停。
这是我当前的代码:
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;
},
如何调整 calculateRatiosForData
一次处理 N 行,然后暂停?
这将使它成为异步的,我正在努力调整我的代码来处理这个问题。
我做什么当然需要IE8支持!
我会说在计算比率之前将数据拼接成 N 行。使计算比率成为一个单一的功能,即。你程序的这一部分 // do some calculations...
然后使用 Q.
承诺它
之后,您可以创建一个承诺数组,每个承诺都是 calculateRatiosForData(Nth row)
。
之后您可以拨打Promise.all(yourArrayOfCalculateRatioPromises)
。
这里的问题是您仍将在浏览器上计算所有这些数据。如果可能,最好将该处理卸载到服务器上并使用 POST
请求进行计算。 promise 结构看起来还是一样的。
还有一个问题是您的脚本的其余部分是否需要这些计算比率。如果你做得不好,那么你只需将脚本的其余部分封装在 Promise.all(arrayOfPromises).then(function (result) { //rest of script}
中。该代码的关键部分是 .then(function () {}).
我建议使用 WebWorkers but alas they are not supported by IE8. There are workarounds found in google code and also here,但我不能保证这些选项的效果如何。
编辑:这将展示如何做出承诺
基本上有两种方法可以做到这一点。
1) 你可以把calculateRatios函数写成一个节点的样式,然后用Q来promisify它。
function calculateRatios (arrayInput, callback) {
//error checking if error
//callback(error)
//calculate the ratios algorithm then do
setTimeout(callback(undefined, data), 500);
}
然后承诺它看起来像这样:
var Promise = require('q'), //however you want to do this in the browser
calculateRatiosAsync = Promise.promisify(calculateRatios);
我个人喜欢这种方式,因为它可以与其他控制流库兼容,而无需更改原始函数,或者如果不需要 promisify,您可以按照现有的方式使用原始函数。
2) 另一种方法是显式创建承诺。
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();
}
注意: 应该注意的是,您将不得不以不同的方式要求 promise 库,但我将其留给您。
我正在处理一个数据密集型网站,我需要支持 IE8。我在 IE8 中遇到了一些 "slow-running script" 错误,因此我正在调整我的代码以在旧浏览器的循环期间定期暂停。
这是我当前的代码:
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;
},
如何调整 calculateRatiosForData
一次处理 N 行,然后暂停?
这将使它成为异步的,我正在努力调整我的代码来处理这个问题。
我做什么当然需要IE8支持!
我会说在计算比率之前将数据拼接成 N 行。使计算比率成为一个单一的功能,即。你程序的这一部分 // do some calculations...
然后使用 Q.
之后,您可以创建一个承诺数组,每个承诺都是 calculateRatiosForData(Nth row)
。
之后您可以拨打Promise.all(yourArrayOfCalculateRatioPromises)
。
这里的问题是您仍将在浏览器上计算所有这些数据。如果可能,最好将该处理卸载到服务器上并使用 POST
请求进行计算。 promise 结构看起来还是一样的。
还有一个问题是您的脚本的其余部分是否需要这些计算比率。如果你做得不好,那么你只需将脚本的其余部分封装在 Promise.all(arrayOfPromises).then(function (result) { //rest of script}
中。该代码的关键部分是 .then(function () {}).
我建议使用 WebWorkers but alas they are not supported by IE8. There are workarounds found in google code and also here,但我不能保证这些选项的效果如何。
编辑:这将展示如何做出承诺
基本上有两种方法可以做到这一点。
1) 你可以把calculateRatios函数写成一个节点的样式,然后用Q来promisify它。
function calculateRatios (arrayInput, callback) {
//error checking if error
//callback(error)
//calculate the ratios algorithm then do
setTimeout(callback(undefined, data), 500);
}
然后承诺它看起来像这样:
var Promise = require('q'), //however you want to do this in the browser
calculateRatiosAsync = Promise.promisify(calculateRatios);
我个人喜欢这种方式,因为它可以与其他控制流库兼容,而无需更改原始函数,或者如果不需要 promisify,您可以按照现有的方式使用原始函数。
2) 另一种方法是显式创建承诺。
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();
}
注意: 应该注意的是,您将不得不以不同的方式要求 promise 库,但我将其留给您。