我正在使用threads.js,不幸的是,我不得不从多个二进制文件中加载数据,而不是从服务器中提取数据(不要问...长话短说)。
resolvedData: function (currUser, role, loggedUser, user, CSData, resolved, $q, CSS, Manager, Segments, TOPData) {
var data = [];
var openData = [];
var allOpenData = [];
var start = new Date().getTime();
var myArr, elapsed;
var promises = [];
for (var i = 0; i < 16; i++) {
let num = i + 1;
promises.push(user.readBinary(CSData.path + 'CSData' + num + '.xlsb').then(function (response) {
//transform into an array before passing it in
myArr = new Uint8Array(response);
//run these in a pool to use the next open thread
pool
.run(function (input, done) {
//transform the data
var workbook = XLSX.read(input, { type: "array" });
var myJSON = XLSX.utils.sheet_to_json(workbook.Sheets.Sheet1);
//return the JSON array
done.transfer(myJSON, [])
}, ["https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.13.0/xlsx.full.min.js"]) //import XLSX
.send(myArr, [myArr.buffer]) //pass in the transferable object
//when each thread is complete add that JSON data to the data array
.on('done', function (myJSON) {
data = data.length > 0 ? data.concat(myJSON) : myJSON;
elapsed = new Date().getTime() - start;
console.log('Thread ' + num + ' finished. Total Elapsed time: ' + elapsed / 1000);
console.log('Processed ' + data.length + ' records');
});
return response;
}));
}
//kill the threads and return the data
pool.on('finished', function () {
pool.killAll();
//if they are a CSS we are only returning their data. just look for the employee Id as this will pick up any of their info
if (loggedUser.role === 'CSS') data = data.filter(d => d.Query_Created_By.includes(loggedUser.empId));
resolved.data = data;
});
$.when.apply($, promises).then(function (response) {
return data;
});
}
user.readBinary是一个角度服务,它创建Ajax传输以将其作为ArrayBuffer读入文件,然后使用dataType Binary调用普通的Ajax GET。代码如下:
this.readBinary = function (url) {
// use this transport for "binary" data type
$.ajaxTransport("+binary", function (options, originalOptions, jqXHR) {
// check for conditions and support for blob / arraybuffer response type
if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob))))) {
return {
// create new XMLHttpRequest
send: function (headers, callback) {
// setup all variables
var xhr = new XMLHttpRequest(),
url = options.url,
type = options.type,
async = options.async || true,
// blob or arraybuffer. Default is blob
dataType = options.responseType || "blob",
data = options.data || null,
username = options.username || null,
password = options.password || null;
xhr.addEventListener('load', function () {
var data = {};
data[options.dataType] = xhr.response;
// make callback and send data
callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
});
xhr.open(type, url, async, username, password);
// setup custom headers
for (var i in headers) {
xhr.setRequestHeader(i, headers[i]);
}
xhr.responseType = dataType;
xhr.send(data);
},
abort: function () {
jqXHR.abort();
}
};
}
});
return $.ajax({
url: url,
method: 'GET',
dataType: 'binary',
processData: 'false',
responseType: 'arraybuffer',
headers: { 'X-Requested-With': 'XMLHttpRequest' }
}).then(function (response) {
return response
}, function (error) {
alertify.error('There was an error returning the Binary ArrayBuffer! Error:' + error.name + ':' + error.status)
});
};
问题是,$。when.apply在所有诺言都解决之前就解决了。我不确定它是否是多线程的,但是我无法让它等到它完成之后再转到其他代码。这是通过ui-router状态解决的,因此页面在信息可用之前就已加载,这在尝试显示正在加载的数据时会引起问题。
我需要怎么做才能按预期工作?