map.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import Promise from './promise';
  2. import {
  3. isFunction,
  4. isArray
  5. } from './utils';
  6. /**
  7. `RSVP.map` is similar to JavaScript's native `map` method, except that it
  8. waits for all promises to become fulfilled before running the `mapFn` on
  9. each item in given to `promises`. `RSVP.map` returns a promise that will
  10. become fulfilled with the result of running `mapFn` on the values the promises
  11. become fulfilled with.
  12. For example:
  13. ```javascript
  14. let promise1 = RSVP.resolve(1);
  15. let promise2 = RSVP.resolve(2);
  16. let promise3 = RSVP.resolve(3);
  17. let promises = [ promise1, promise2, promise3 ];
  18. let mapFn = function(item){
  19. return item + 1;
  20. };
  21. RSVP.map(promises, mapFn).then(function(result){
  22. // result is [ 2, 3, 4 ]
  23. });
  24. ```
  25. If any of the `promises` given to `RSVP.map` are rejected, the first promise
  26. that is rejected will be given as an argument to the returned promise's
  27. rejection handler. For example:
  28. ```javascript
  29. let promise1 = RSVP.resolve(1);
  30. let promise2 = RSVP.reject(new Error('2'));
  31. let promise3 = RSVP.reject(new Error('3'));
  32. let promises = [ promise1, promise2, promise3 ];
  33. let mapFn = function(item){
  34. return item + 1;
  35. };
  36. RSVP.map(promises, mapFn).then(function(array){
  37. // Code here never runs because there are rejected promises!
  38. }, function(reason) {
  39. // reason.message === '2'
  40. });
  41. ```
  42. `RSVP.map` will also wait if a promise is returned from `mapFn`. For example,
  43. say you want to get all comments from a set of blog posts, but you need
  44. the blog posts first because they contain a url to those comments.
  45. ```javscript
  46. let mapFn = function(blogPost){
  47. // getComments does some ajax and returns an RSVP.Promise that is fulfilled
  48. // with some comments data
  49. return getComments(blogPost.comments_url);
  50. };
  51. // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled
  52. // with some blog post data
  53. RSVP.map(getBlogPosts(), mapFn).then(function(comments){
  54. // comments is the result of asking the server for the comments
  55. // of all blog posts returned from getBlogPosts()
  56. });
  57. ```
  58. @method map
  59. @static
  60. @for RSVP
  61. @param {Array} promises
  62. @param {Function} mapFn function to be called on each fulfilled promise.
  63. @param {String} label optional string for labeling the promise.
  64. Useful for tooling.
  65. @return {Promise} promise that is fulfilled with the result of calling
  66. `mapFn` on each fulfilled promise or value when they become fulfilled.
  67. The promise will be rejected if any of the given `promises` become rejected.
  68. @static
  69. */
  70. export default function map(promises, mapFn, label) {
  71. if (!isArray(promises)) {
  72. return Promise.reject(new TypeError("RSVP.map must be called with an array"), label);
  73. }
  74. if (!isFunction(mapFn)) {
  75. return Promise.reject(new TypeError("RSVP.map expects a function as a second argument"), label);
  76. }
  77. return Promise.all(promises, label).then(values => {
  78. let length = values.length;
  79. let results = new Array(length);
  80. for (let i = 0; i < length; i++) {
  81. results[i] = mapFn(values[i]);
  82. }
  83. return Promise.all(results, label);
  84. });
  85. }