我正在尝试解决这个承诺难题,我有两个问题:
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));
答案 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_));