admin管理员组

文章数量:1415697

I'm trying to figure out the most efficient way to wait inside map function until all datas are fetched and then continue. I tried with the 'bluebird' library and came out with this.

Is this even working right and is there even better way to achieve this?

let urls = ['.jpg', '.jpg', '.jpeg'];

let test = [];

Promise.map(urls, function(url) {
    // Promise.map awaits for returned promises as well.
    return getThumb(url);
}).then(function() {
    console.log(test);
});

function getThumb(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
    test.push(url);
  });

/

Thanks :)

Edit:

This is the final oute:

let urls = ['.jpg', '.jpg', '.jpeg'];

Promise.map(urls, getThumb).then(function(data) {
  console.log(data.length);
}).catch(e => console.error(e));

function getThumb(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
  });
};

I'm trying to figure out the most efficient way to wait inside map function until all datas are fetched and then continue. I tried with the 'bluebird' library and came out with this.

Is this even working right and is there even better way to achieve this?

let urls = ['https://static.pexels./photos/36753/flower-purple-lical-blosso.jpg', 'https://static.pexels./photos/36764/marguerite-daisy-beautiful-beauty.jpg', 'https://static.pexels./photos/65609/tulip-tulips-sharpness-game-flower-65609.jpeg'];

let test = [];

Promise.map(urls, function(url) {
    // Promise.map awaits for returned promises as well.
    return getThumb(url);
}).then(function() {
    console.log(test);
});

function getThumb(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
    test.push(url);
  });

https://jsfiddle/v80wmmsv/4/

Thanks :)

Edit:

This is the final oute:

let urls = ['https://static.pexels./photos/36753/flower-purple-lical-blosso.jpg', 'https://static.pexels./photos/36764/marguerite-daisy-beautiful-beauty.jpg', 'https://static.pexels./photos/65609/tulip-tulips-sharpness-game-flower-65609.jpeg'];

Promise.map(urls, getThumb).then(function(data) {
  console.log(data.length);
}).catch(e => console.error(e));

function getThumb(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
  });
};
Share Improve this question edited Jul 24, 2017 at 11:54 Jack M. asked Jul 24, 2017 at 11:22 Jack M.Jack M. 2,0315 gold badges26 silver badges36 bronze badges 3
  • Did you try it? Is there a problem you are seeing? – Ruan Mendes Commented Jul 24, 2017 at 11:28
  • I cant figure how to console.log to be sure if it works correctly. I just push the function parameter to an array at the end of the xhr and then log the array when map is done. I'm not very good with these async things – Jack M. Commented Jul 24, 2017 at 11:33
  • @JackM.: "I just push the function parameter to an array at the end of the xhr..." To be clear, you push it at the start of the XHR, not when it finishes. – T.J. Crowder Commented Jul 24, 2017 at 11:41
Add a ment  | 

2 Answers 2

Reset to default 2

If you want to concurrently run all promises and do something when all of them are resolved, you can use es2015 Promise.all():

let urls = ['https://static.pexels./photos/36753/flower-purple-lical-blosso.jpg', 'https://static.pexels./photos/36764/marguerite-daisy-beautiful-beauty.jpg', 'https://static.pexels./photos/65609/tulip-tulips-sharpness-game-flower-65609.jpeg'];

let test = [];

Promise.all(urls.map(getThumb)).then(function() {
    console.log(test);
});

function getThumb(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
    test.push(url);
  });
};

Some notes about that code, which may or may not be issues depending on what you want:

  • test will end up with the URLs in the order in which they were requested (which I'm fairly sure is the same as their order in the original array, looking at the Promise.map documentation), not the order in which they were resolved (if you care)
  • test will contain the URLs even if they failed to load, since you're pushing them in the mapping function
  • You're resolving your individual promises with the text (well, image data) of the response, but not using that text anywhere
  • You're using an unnecessary wrapper function, no need for the wrapper around getThumb:

    Promise.map(urls, getThumb).then(function() {
        console.log(test);
    });
    

And one definite issue:

  • You're not handling failure: You need a catch (or a then with the second [failure] callback).

Other than the lack of error handling, if the above is what you want, that code is fine.

本文标签: loopsJavascript ES6 Promises with mapStack Overflow