evt.target.result is empty? - javascript

For some reason, in the following code, evt.target.result is empty. Why is that?
function drop(evt) {
evt.stopPropagation();
evt.preventDefault();
var file = evt.dataTransfer.files[0];
handleFiles(file, evt.target);
}
function handleFiles(file, target) {
loadSongAnimate();
var reader = new FileReader();
// init the reader event handlers
reader.onloadend = handleReaderLoadEnd;
// begin the read operation
reader.readAsDataURL(file);
}
function handleReaderLoadEnd(evt) {
alert('Passing this: ' + evt.target.result);
document.getElementById('audioTagId').src = evt.target.result;
}

From the fine manual:
onloadend
Called when the read is completed, whether successful or not. This is called after either onload or onerror.
I suspect that you have an error condition. Add an onerror callback and have a look at what reader.error has to say. You might want to use separate onerror, onabort, and onload callbacks instead of onloadend:
onabort
Called when the read operation is aborted.
onerror
Called when an error occurs.
onload
Called when the read operation is successfully completed.
That might make it easier to handle the individual events.
In your comment you say that you're getting an "error 2", from the other fine manual:
Constant: SECURITY_ERR
Value: 2
Description: The file could not be accessed for security reasons.
So it looks like you getting a "permission denied" error.

I was editing and viewing the file over a local file:// protocol. When you are referencing a local file inside another local file, the blank headers in the referenced local file with throw security errors.
Lesson learned... always upload to a server for testing as well. Would have saved me hours of Googling, and lots of hair.

Related

How to catch silent NS_ERROR_OUT_OF_MEMORY in Chrome

I tested the loading of very large files with XMLHttpRequest and noticed an interesting behavior of Chrome (90.0.4430.212): It loads the full file, but finishes with a 200-OK code and and empty (!) result. First I thought it was a silent timeout or whatever, but no, it seems to be a reached memory limit.
Trying it in Firefox (13.0esr (64-bit)) took for ages, but in the end I knew more: The Transfer itself did not trigger an "error" or a "timeout" event, resulted with 200 and empty result as well. But it threw an error:
Exception { name: "NS_ERROR_OUT_OF_MEMORY", message: "", result: 2147942414, filename: "http://localhost/testcenter-backend/vo_data/teterei.html", lineNumber: 16, columnNumber: 0, data: null, stack: "transferComplete#http://localhost/testcenter-backend/vo_data/teterei.html:16:9\n" }
So it has nothing to do with the transport itself, but apparently a memory limit reached when trying to do anything with the result. When I don't use the oReq.response, the error does not appear.
Okay, how to handle this? In Firefox I can catch the error with a simple try catch block. But this does not work for Chrome. A naive approach would be just to check if the resulting content is empty, but I wonder if there is another possibility to detect this stuff happening.
--
How to reproduce:
Create a huge file.
I generated a 10,4GB file this way:
dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*10000]
Run this code in a browser to load it.
const oReq = new XMLHttpRequest();
function updateProgress (oEvent) {
console.log("progress", oEvent.loaded);
}
function transferComplete(evt) {
console.log("The transfer is complete.", oReq.getAllResponseHeaders(), oReq.status);
console.log(oReq.response); // here too much memory is allocated
}
function transferFailed(evt) {
console.log("error", oReq.getAllResponseHeaders(), oReq.status);
}
function transferCanceled(evt) {
console.log("cancel", oReq.getAllResponseHeaders(), oReq.status);
}
function timeOut(evt) {
console.log("timeout", oReq.getAllResponseHeaders(), oReq.status);
}
oReq.addEventListener("progress", updateProgress);
oReq.addEventListener("load", transferComplete);
oReq.addEventListener("error", transferFailed);
oReq.addEventListener("abort", transferCanceled);
oReq.addEventListener("timeout", timeOut);
// your huge file here instead
oReq.open("GET", "https://cdn.jsdelivr.net/npm/jquery#3.2.1/dist/jquery.min.js"); // URL to huge file here
oReq.send();
The actual memory limit may vary to your system.

Calling readStream.destroy() on a node js read stream doesn't stop the reading

I hope you are all doing well.
I am facing an issue with streams in Node Js and I would like to solicit your help:
I am reading a file with: const readStream = fs.createReadStream('./veryBigFile');
and I pipe the output to a POST request like this:
readStream.pipe(post_req);
However, I would like to stop the reading from the file after a certain timeout , and also to stop the POST request.
I tried both readStream.close() and readStream.destroy() but they don't work (I attached an 'end' listener to readStream, and it doesn't get triggered after the timeout).
Any ideas ?
After your comment kirill Groshkov, I decided to take a look again at my code and I understood how to make it work !
After a destroy event is tirggered (with readStream.destroy()), it is an 'error' event that is emitted, not an 'end' event which I was listening to.
So I still had to use readStream.destroy('YOUR CUSTOM ERROR MESSAGE') to stop reading from the file after timeout.
Then I listened to this custom error with:
readStream.on('error', e => {
if (e === 'YOUR CUSTOM ERROR MESSAGE') {
post_req.abort(); //To cancel request
// etc.
} else {
reject(`An error occured while uploading data: ${e}`);
}
});

With new Audio(), is there any way to find out of the audio file exists?

Is there any way to find out if an audio file exists from the initialized Audio instance?
For example, if I try to compare an existing audio and a non-existing audio file:
new Audio('exists.mp3').readyState => 0
new Audio('does_not_exist.mp3').readyState => 0
(HTTP "Content-Type" of "text/html" is not supported. Load of media resource http://amc.narom.no/Steid failed.)
The return value is the same, but the console logs the error of not being able to load the media resource. Is there a way to catch this message, or using any method within the Audio object to find out whether the audio file exists or not?
Note:
I know I can do a HttpRequest or AJAX request to the source of the audio to check if it exists, but was wondering if this could be done in a more effective way.
Not synchronously, so immediately accessing a property will not work as you must wait for the browser to attempt the network request, but yes, you can use the error and loadeddata events (optionally substituting other similar media events to determine success) .
var a = new Audio('doesitexist.mp3');
a.onerror = function() {
console.log('File does not exist.');
};
a.onloadeddata = function() {
console.log('File exists.');
};
The loadeddata event will not fire until at least some data has successfully been loaded, and error will fire if the request returned an invalid response like a 404 error.

Jsdom throws an error on a external resource script (script on the page) after returning the result

I am getting an error which seems to be originating from one of the page scripts.
file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1
return c.apply(undefined,a)}catch(d){webengage.eLog(d);if(!b){throw d}}}else{t
^
TypeError: Cannot call method 'call' of undefined
at new exports.NOT_IMPLEMENTED (/usr/local/lib/node_modules/jsdom/lib/jsdom/browser/utils.js:9:13)
at Object.webengage.eLog (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:366)
at t.extend.u (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:19160)
at Object.t.extend.error (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:19299)
at file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:66518
at Object.webengage.withELog (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:640)
at Timer.<anonymous> (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:937)
at Timer.exports.setInterval.timer.ontimeout (timers.js:234:14)
I am getting this error from the following code:
try {
var document = jsdom.jsdom(str, null, {});
} catch(e) {
console.log("Got ERROR...");
console.log(e);
}
console.log("Page Document Loaded.");
var window = document.parentWindow;
//console.log(window.document.innerHTML);
console.log(window.innerWidth);
console.log(typeof window.document.getElementsByClassName);
here str is the html that i got earlier. I am able to see printed results, the html the innerWidth and the typeof getElementsByClassName i.e.. function. But after around 20 seconds i am getting the above error and my application crashes, without printing Got ERROR... from above.
The first question that i have is why is my application still running after printing the last thing. Is this a normal behavior for jsdom that it keeps on running like how in a browser a script keeps on running until window.close() is given.
The actual problem is, how can i resolve this. I want to trigger few events in this window object and interact with it but it keeps on crashing.
The url for the script is a little confusing:
file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1
this is because the page is fetching this script resource in an ajax call with the url:
//cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1
although jsdom is able to get the resource, i checked that this script has that line where it is showing the error.

FileReaderSync undefined inside Web Worker in Firefox extension using Add-on SDK

I managed to get a Web Worker (not a content/worker) in my Firefox add-on using the Add-on SDK. I followed Wladimir's advice here to get the Worker class working: Concurrency with Firefox add-on script and content script
Now, I can launch a worker in my code and can talk to it by sending/receiving messages.
This is my main.js file:
// spawn our log reader worker
var worker = new Worker(data.url('log-reader.js'));
// send and respond to some dummy messages
worker.postMessage('halo');
worker.onmessage = function(event) {
console.log('received msg from worker: ' + event.data);
};
This is my log-reader.js file:
// this function gets called when main.js sends a msg to this worker
// using the postMessage call
onmessage = function(event) {
var info = event.data;
// reply back
postMessage('hey addon, i got your message: ' + info);
if (!!FileReaderSync) {
postMessage('ERROR: FileReaderSync is not supported');
} else {
postMessage('FileReaderSync is supported');
}
// var reader = new FileReaderSync();
// postMessage('File contents: ' + reader.readAsText('/tmp/hello.txt'));
};
My problem is that the FileReaderSync class is not defined inside the log-reader.js file, and as a result I get the error message back. If I uncomment the last lines where FileReaderSync is actually used, I will never get the message back in my addon.
I tried using the same trick I used for Worker, by creating a dummy.jsm file and importing in main.js, but FileReaderSync will only be available in main.js and not in log-reader.js:
// In dummy.jsm
var EXPORTED_SYMBOLS=["Worker"];
var EXPORTED_SYMBOLS=["FileReaderSync"];
// In main.js
var { Worker, FileReaderSync } = Cu.import(data.url('workers.jsm'));
Cu.unload(data.url("workers.jsm"));
I figure there has to be a solution since the documentation here seems to indicate that the FileReaderSync class should be available to a Web Worker in Firefox:
This interface is only available in workers as it enables synchronous I/O that could potentially block.
So, is there a way to make FileReaderSync available and usable in the my Web Worker code?
Actually, your worker sends "ERROR" if FileReaderSync is defined since you negated it twice. Change !!FileReaderSync to !FileReaderSync and it will work correctly.
I guess that you tried to find the issue with the code you commented out. The problem is, reader.readAsText('/tmp/hello.txt') won't work - this method expects a blob (or file). The worker itself cannot construct a file but you can create it in your extension and send to the worker with a message:
worker.postMessage(new File("/tmp/hello.txt"));
Note: I'm not sure whether the Add-on SDK defines the File constructor, you likely have to use the same trick as for the Worker constructor.
The worker can then read the data from this file:
onmessage = function(event)
{
var reader = new FileReaderSync();
postMessage("File contents: " + reader.readAsText(event.data));
}

Categories