Promise.all始终返回一个空数组

时间:2019-03-20 02:25:27

标签: javascript asynchronous promise

我正在尝试解决这个承诺难题,我有两个问题:

A)我想知道为什么它返回空数组。我在做什么错了?

B)如何实现异步缩减?

B)如何使其返回异步数组而不是空数组?

注意:

  

请使用.get方法遍历元素,然后   返回值必须是asyncArray(不是常规数组)

代码如下:

  /**
     * Async array.
     */
    function AsyncArray(arr) {
      this._arr = arr;
      this.length = arr.length;
    }
    
    /**
     * Asynchronously get the array item of the
     * given index.
     * @param {number} index - array index of the desired item
     * @param {function} callback - called with the array item
     */
    AsyncArray.prototype.get = function get(index, callback) {
      setTimeout(callback, 0, this._arr[index]);
    };
    
    
    /**
     * Async version of Array.prototype.map.
     * @param {AsyncArray} arr
     * @param {function} fn - (item: any) => any
     * @returns {Promise<AsyncArray>}
     */
    function asyncMap(arr, fn) {
      
      let counter = 0; // counter
      const res = []; /// array of promises.
      const len = arr.length;
      
      // Get the length.
      return new Promise((resolve, reject) => { // Pending.
        
        while(true) {
          if(counter===len) {
            console.log("before break", res);
            break;
          }
          
          arr.get(counter, item => {
            res[counter] = function() {
              return new Promise((resolve, reject) => {
                return resolve(fn(item));
              });
            }();
            
            console.log('r',res);
          });
          counter += 1;
        }
      
    
        Promise.all(res).then((r1, rej) => {
          console.log("hello world", r1);
          return resolve(res); 
        });
      });
    }
    
    /**
     * Async version of Array.prototype.reduce.
     * @param {AsyncArray} arr
     * @param {function} fn - (val: any, item: any) => any
     * @returns {Promise<any>}
     */
    function asyncReduce(arr, fn, initVal) {}
    
    
    const arr = new AsyncArray([1, 2, 3]);
    
    // arr.get(1, item => console.log(item)); // Existing
    
    // Expected result: [2, 4, 6];
    asyncMap(arr, x => x * 2).then(arr_ => console.log('asyncMap:', arr_));
    
    // Expected result: 106
    // asyncReduce(arr, (v, x) => v + x, 100).then(val => console.log('asyncReduce:', val));
    

1 个答案:

答案 0 :(得分:3)

您正在将get调用的结果异步放入结果数组 -当您在其上调用res时,Promise.all为空:

      arr.get(counter, item => {
        res[counter] = function() {
          return new Promise((resolve, reject) => {
            return resolve(fn(item));
          });
        }();
      });
      // at this point, nothing has been pushed to res

Promise.all(res)

在那之后同步调用不会等待任何东西,因为数组中的所有项目都不是Promises。

您可以将Promise同步地推送到数组

      res.push(new Promise((resolve) => {
        arr.get(counter, item => resolve(fn(item)));
      }));

/**
     * Async array.
     */
    function AsyncArray(arr) {
      this._arr = arr;
      this.length = arr.length;
    }
    
    /**
     * Asynchronously get the array item of the
     * given index.
     * @param {number} index - array index of the desired item
     * @param {function} callback - called with the array item
     */
    AsyncArray.prototype.get = function get(index, callback) {
      setTimeout(callback, 0, this._arr[index]);
    };
    
    
    /**
     * Async version of Array.prototype.map.
     * @param {AsyncArray} arr
     * @param {function} fn - (item: any) => any
     * @returns {Promise<AsyncArray>}
     */
    function asyncMap(arr, fn) {
      
      let counter = 0; // counter
      const res = []; /// array of promises.
      const len = arr.length;
      
      // Get the length.
      return new Promise((resolve, reject) => { // Pending.
        
        while(true) {
          if(counter===len) {
            console.log("before break", res);
            break;
          }
          res.push(new Promise((resolve) => {
            arr.get(counter, item => resolve(fn(item)));
          }));
          counter += 1;
        }
      
    
        Promise.all(res).then((r1, rej) => {
          console.log("hello world", r1);
          return resolve(r1); 
        });
      });
    }
    
    /**
     * Async version of Array.prototype.reduce.
     * @param {AsyncArray} arr
     * @param {function} fn - (val: any, item: any) => any
     * @returns {Promise<any>}
     */
    function asyncReduce(arr, fn, initVal) {}
    
    
    const arr = new AsyncArray([1, 2, 3]);
    
    // arr.get(1, item => console.log(item)); // Existing
    
    // Expected result: [2, 4, 6];
    asyncMap(arr, x => x * 2).then(arr_ => console.log('asyncMap:', arr_));
    
    // Expected result: 106
    // asyncReduce(arr, (v, x) => v + x, 100).then(val => console.log('asyncReduce:', val));

我宁愿在内部数组长度的数组上使用.map来将每个arr.get调用映射到数组中的Promise,然后在该数组上调用Promise.all:< / p>

function AsyncArray(arr) {
  this._arr = arr;
  this.length = arr.length;
}
AsyncArray.prototype.get = function get(index, callback) {
  setTimeout(callback, 0, this._arr[index]);
};
function asyncMap(asyncArr, fn) {
  return Promise.all(
    new Array(asyncArr.length).fill().map(
      (item, i) => new Promise(resolve => asyncArr.get(i, item => resolve(fn(item))))
    )
  ).then((result) => {
      console.log("hello world", result);
      return result;
    });
}
const arr = new AsyncArray([1, 2, 3]);
asyncMap(arr, x => x * 2).then(arr_ => console.log('asyncMap:', arr_));

对于异步缩减,让累加器成为一个在最后一次迭代中被推入数组后会解析为数组的Promise:

function asyncReduce(asyncArr, fn, initVal) {
  return new Array(asyncArr.length).fill().reduce(
    (a, _, i) => a.then(resultsArr => {
      // feel free to use asynchronous operations here
      return new Promise((resolve) => {
        asyncArr.get(i, resultItem => {
          resultsArr.push(fn(resultItem));
          resolve(resultsArr);
        });
      });
    }),
    Promise.resolve(initVal)
  );
}

function AsyncArray(arr) {
  this._arr = arr;
  this.length = arr.length;
}
AsyncArray.prototype.get = function get(index, callback) {
  setTimeout(callback, 0, this._arr[index]);
};
const arr = new AsyncArray([1, 2, 3]);
asyncReduce(arr, x => x * 2, []).then(arr_ => console.log('asyncReduce:', arr_));

要还返回asyncArray的实例,只需在解决之前调用new AsyncArray,例如:

function asyncReduce(asyncArr, fn, initVal) {
  return new Array(asyncArr.length).fill().reduce(
    (a, _, i) => a.then(resultsArr => {
      // feel free to use asynchronous operations here
      return new Promise((resolve) => {
        asyncArr.get(i, resultItem => {
          resultsArr.push(fn(resultItem));
          resolve(resultsArr);
        });
      });
    }),
    Promise.resolve(initVal)
  )
    .then((resultArr) => new AsyncArray(resultArr));
}

function AsyncArray(arr) {
  this._arr = arr;
  this.length = arr.length;
}
AsyncArray.prototype.get = function get(index, callback) {
  setTimeout(callback, 0, this._arr[index]);
};
const arr = new AsyncArray([1, 2, 3]);
asyncReduce(arr, x => x * 2, []).then(arr_ => console.log('asyncReduce:', arr_));