I'm actually developping a text editor and just got stuck with an issue regarding the image upload and display method.
What I'm trying to achieve
On the click of a button in the toolbar, the app displays a pop-up for uploading a picture. The user can then drag'n drop the file or click and select the file through his file system. After the image is selected, I send it to the server through ajax which uploads it and stores it in a folder. Once this is done, the server sends a response that the file is okay and ready to use. The function then resolves and the editor adds the proper link to the image.
I tried something that worked while attaching event listeners in the promise.
function uploadImage(editor) {
/* Displays the pop-up */
uploadView.style.display = "block";
var promise = new Promise(function(resolve, reject) {
uploadInput.addEventListener('change', function(event) {
/* ajax call */
resolve(value);
});
dropZone.addEventListener('drop', function(event) {
/* ajax call */
resolve(value);
});
});
promise.then(function(result) {
/* Adds the link */
}, function(err) {
/* handles errors */
});
}
It's all good, but everytime you trigger the function, a new listener is attached and the function inside runs another time per new click...
I then thought I might remove the listeners after the promise resolves. However, in order to do so, I can't make use of anonymous functions but then I can't use my resolve method inside as it throws an error.
This is not working:
function uploadImage(editor) {
/* Displays the pop-up */
uploadView.style.display = "block";
var promise = new Promise(function(resolve, reject) {
uploadInput.addEventListener('change', handleUpload);
dropZone.addEventListener('drop', handleUpload);
});
promise.then(function(result) {
/* Adds the link */
/* Removes the listeners */
uploadInput.removeEventListener('change', handleUpload);
dropZone.removeEventListener('drop', handleUpload);
}, function(err) {
/* Handles errors */
/* Removes the listeners */
uploadInput.removeEventListener('change', handleUpload);
dropZone.removeEventListener('drop', handleUpload);
});
}
function handleUpload(event) {
if (event.type == "change") {
/* ajax call */
resolve(value); // Throws an error
} else {
/* ajax call */
resolve(value); // Throws an error
}
}
I'm running out of idea...
in order to do so, I can't make use of anonymous functions but then I can't use my resolve method inside
There's no reason to move the function(s) outside of the uploadImage
function or the new Promise
callback when naming them or converting them to declarations:
var promise = new Promise(function(resolve, reject) {
function handleUpload(event) {
/* Removes the listeners */
uploadInput.removeEventListener('change', handleUpload);
dropZone.removeEventListener('drop', handleUpload);
resolve(event); // works just fine
}
uploadInput.addEventListener('change', handleUpload);
dropZone.addEventListener('drop', handleUpload);
});
promise.then(function(event) {
if (event.type == "change") {
return /* ajax call */
} else {
return /* other ajax call */
}
}).then(function(result) {
/* Adds the link */
}, function(err) {
/* Handles errors */
});
ElementTarget.addEventListener()
takes three arguments. The event name, a callback and an options object. Now this options object is interesting and can be handy since it includes a boolean property called once
. What does it do..?
Cool. Then you may simply change your first snippet as follows;
function uploadImage(editor) {
/* Displays the pop-up */
uploadView.style.display = "block";
var promise = new Promise(function(resolve, reject) {
uploadInput.addEventListener('change', function(event) {
/* ajax call */
resolve(value);
},{once: true}); // remove event after run once
dropZone.addEventListener('drop', function(event) {
/* ajax call */
resolve(value);
},{once: true}); // remove event after run once
});
promise.then(function(result) {
/* Adds the link */
}, function(err) {
/* handles errors */
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With