Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #35238 > unrolled thread

Array of Files to array of data url

Started byAndrew Poulos <ap_prog@hotmail.com>
First post2018-06-19 19:44 +1000
Last post2018-06-21 15:16 -0700
Articles 6 — 5 participants

Back to article view | Back to comp.lang.javascript


Contents

  Array of Files to array of data url Andrew Poulos <ap_prog@hotmail.com> - 2018-06-19 19:44 +1000
    Re: Array of Files to array of data url Jake Jarvis <pig_in_shoes@yahoo.com> - 2018-06-19 12:28 +0200
    Re: Array of Files to array of data url Jon Ribbens <jon+usenet@unequivocal.eu> - 2018-06-19 14:47 +0000
    Re: Array of Files to array of data url Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2018-06-20 21:47 +0200
      Re: Array of Files to array of data url Andrew Poulos <ap_prog@hotmail.com> - 2018-06-21 15:33 +1000
    Re: Array of Files to array of data url "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2018-06-21 15:16 -0700

#35238 — Array of Files to array of data url

FromAndrew Poulos <ap_prog@hotmail.com>
Date2018-06-19 19:44 +1000
SubjectArray of Files to array of data url
Message-ID<8dGdnZA1WKvpTbXGnZ2dnUU7-e3NnZ2d@westnet.com.au>
I have this array

var files = [File, File, null, File];

and I need to create a new array with the data from each File (or null 
if it's null).

I tried

var newarr = files.map(function(el){
   if (el === null) return null;

   var reader = new FileReader();

   reader.addEventListener("load", function () {
     return reader.result;
   }, false);

   reader.readAsDataURL(el);
});

but the array only ever gets populated with null. How can this be done?

Andrew Poulos

[toc] | [next] | [standalone]


#35239

FromJake Jarvis <pig_in_shoes@yahoo.com>
Date2018-06-19 12:28 +0200
Message-ID<pgalt3$hdf$1@dont-email.me>
In reply to#35238
Am 19.06.2018 um 11:44 schrieb Andrew Poulos:
> I have this array
> 
> var files = [File, File, null, File];
> 
> and I need to create a new array with the data from each File (or null 
> if it's null).
> 
> I tried
> 
> var newarr = files.map(function(el){
>    if (el === null) return null;
> 
>    var reader = new FileReader();
> 
>    reader.addEventListener("load", function () {
>      return reader.result;
>    }, false);
> 
>    reader.readAsDataURL(el);
> });
> 
> but the array only ever gets populated with null. How can this be done?
> 
> Andrew Poulos

File API is asynchronous. ("Don't call us, we'll call you")

No idea what the big picture is, maybe those new Promise things can help.

[toc] | [prev] | [next] | [standalone]


#35240

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2018-06-19 14:47 +0000
Message-ID<slrnpii5sq.3qm.jon+usenet@sable.unequivocal.eu>
In reply to#35238
On 2018-06-19, Andrew Poulos <ap_prog@hotmail.com> wrote:
> I have this array
>
> var files = [File, File, null, File];
>
> and I need to create a new array with the data from each File (or null 
> if it's null).
>
> I tried
>
> var newarr = files.map(function(el){
>    if (el === null) return null;
>
>    var reader = new FileReader();
>
>    reader.addEventListener("load", function () {
>      return reader.result;
>    }, false);
>
>    reader.readAsDataURL(el);
> });
>
> but the array only ever gets populated with null. How can this be done?

You're not returning a value from your map function, except when the
element is null. You'd need to do something like:

  function loadAll (files, complete) {
    var results = []
    var nResults = 0
    var expected = 0
    files.forEach(function () { expected += 1 })
    function received (result, index) {
      results[index] = result
      nResults += 1
      if (nResults >= expected) complete(results)
    }
    files.forEach(function (file, index) {
      if (file === null) return received(null, index)
      var reader = new FileReader()
      reader.onload = function () { received(reader.result, index) }
      reader.onabort = reader.onerror = function (event) {
        received(event.type, index)
      }
      reader.readAsDataURL(file)
    })
  }

and then do:

  var files = [File, File, null, File]
  loadAll(files, function (results) {
    // do something with the loaded files, checking for aborts/errors also
  })

Note I haven't tested this code.

[toc] | [prev] | [next] | [standalone]


#35254

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2018-06-20 21:47 +0200
Message-ID<d6b53130-1df1-d8fc-0ac6-3949f37bfe54@PointedEars.de>
In reply to#35238
Andrew Poulos wrote:
> var newarr = files.map(function(el){
>    if (el === null) return null;
> 
>    var reader = new FileReader();
> 
>    reader.addEventListener("load", function () {
               ^^^^^^^^^^^^^
>      return reader.result;
>    }, false);
> 
>    reader.readAsDataURL(el);
> });
> 
> but the array only ever gets populated with null. How can this be done?

It is the (unfortunately common) mistake of expecting something to work
synchronously when it *clearly* does not.  With minimum changes, untested:

  var newarr = []:
  var loaded = 0;

  function allLoaded ()
  {
    … newarr …
  }

  files
    .forEach(function (el, i, a) {
      /* consider: if (!el) */
      if (el === null) return;

      var reader = new FileReader();

      reader.addEventListener("load", function () {
        newarr[i] = reader.result;
        ++loaded;
        if (loaded === a.length) allLoaded();
      }, false);

      reader.readAsDataURL(el);
    });

If you can live with the fact that the indexes do not match, you should
filter the array so that the callback is not called for null elements in
the first place and call Array.prototype.push() instead.

If you want to process the results in any case (whether successful or not),
you have to handle the “error” event and increase in its listener the
“loaded” counter as well (you should rename it then).


PointedEars
-- 
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
  -- Richard Cornford, cljs, <f806at$ail$1$8300dec7@news.demon.co.uk>

[toc] | [prev] | [next] | [standalone]


#35259

FromAndrew Poulos <ap_prog@hotmail.com>
Date2018-06-21 15:33 +1000
Message-ID<N4OdnS1AXoc3pbbGnZ2dnUU7-bfNnZ2d@westnet.com.au>
In reply to#35254
On 21/06/2018 5:47 AM, Thomas 'PointedEars' Lahn wrote:
> Andrew Poulos wrote:
>> var newarr = files.map(function(el){
>>     if (el === null) return null;
>>
>>     var reader = new FileReader();
>>
>>     reader.addEventListener("load", function () {
>                 ^^^^^^^^^^^^^
>>       return reader.result;
>>     }, false);
>>
>>     reader.readAsDataURL(el);
>> });
>>
>> but the array only ever gets populated with null. How can this be done?
> 
> It is the (unfortunately common) mistake of expecting something to work
> synchronously when it *clearly* does not.  With minimum changes, untested:

When things fail (and I miss the forest for the trees) I run out of 
options :-(

>    var newarr = []:
>    var loaded = 0;
> 
>    function allLoaded ()
>    {
>      … newarr …
>    }
> 
>    files
>      .forEach(function (el, i, a) {
>        /* consider: if (!el) */
>        if (el === null) return;
> 
>        var reader = new FileReader();
> 
>        reader.addEventListener("load", function () {
>          newarr[i] = reader.result;
>          ++loaded;
>          if (loaded === a.length) allLoaded();
>        }, false);
> 
>        reader.readAsDataURL(el);
>      });
> 
> If you can live with the fact that the indexes do not match, you should
> filter the array so that the callback is not called for null elements in
> the first place and call Array.prototype.push() instead.
> 
> If you want to process the results in any case (whether successful or not),
> you have to handle the “error” event and increase in its listener the
> “loaded” counter as well (you should rename it then).

Thanks, it's similar to what glathoud suggested.

Andrew Poulos

[toc] | [prev] | [next] | [standalone]


#35266

From"Michael Haufe (TNO)" <tno@thenewobjective.com>
Date2018-06-21 15:16 -0700
Message-ID<02d04815-0dc7-4633-ab3a-1434d1fe6601@googlegroups.com>
In reply to#35238
On Tuesday, June 19, 2018 at 4:44:32 AM UTC-5, Andrew Poulos wrote:
> I have this array
> 
> var files = [File, File, null, File];
> 
> and I need to create a new array with the data from each File (or null 
> if it's null).
> 
> I tried
> 
> var newarr = files.map(function(el){
>    if (el === null) return null;
> 
>    var reader = new FileReader();
> 
>    reader.addEventListener("load", function () {
>      return reader.result;
>    }, false);
> 
>    reader.readAsDataURL(el);
> });
> 
> but the array only ever gets populated with null. How can this be done?


To add to the other examples given:

<script type="text/typescript">

function fileToDataUri(file: File): Promise<string> {
    return new Promise<string>((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsDataURL(file);
    });
}

//...

Promise.all(
    files.map(fileToDataUri)
).then(results => {
    ...
}).catch(errors => {
    ...
})

</script>

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web