Reduce 实现 Promise 串行执行
Opened this issue · 5 comments
function runPromiseByQueue (myPromises) {
myPromises.reduce(
(previousPromise, nextPromise) => previousPromise.then(() => nextPromise()),
Promise.resolve()
)
}
上一个 Promise 执行,完毕后调用下一个 Promise,并作为一个新的 Promise 返回,下次迭代继续这个循环。
const createPromise = (time, id) => () =>
new Promise(resolve =>
setTimeout(() => {
console.log("promise", id)
resolve()
}, time)
)
runPromiseByQueue([
createPromise(3000, 1),
createPromise(2000, 2),
createPromise(1000, 3),
])
// loading 3000 ms
// promise 1
// loading 2000 ms
// promise 2
// loading 1000 ms
// promise 3
Reduce
的作用是在内存中生成这个队列,而不需要把这个冗余的队列写在代码里。
在 async/await 的支持下,runPromiseByQueue 函数可以更为简化:
async function runPromiseByQueue(myPromises) {
for (let func of myPromises) {
await func();
}
}
更多 Promise 扩展:promise-fun
Reduce Polyfill
Array.prototype.reduce2 = function(callback /*, initialValue*/) {
if (this === null) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
var thisArr = Object(this), // thisArr 调用该方法的数组
len = thisArr.length >>> 0, // 数组的长度,`x >>> 0` 保证 x 为正整数
index = 0, // index 下标
value; // 每次传入累加器的值
// 如果参数长度大于等于二,说明传入了初始值,
// 去拿下标为 1 的值作为初始值
if (arguments.length >= 2) {
value = arguments[1];
} else {
// 判断数组里的空位,将数组里的第一个非falsy值初始化为初始值 value
while (index < len && !(index in thisArr)) {
index++;
}
// 此时传入的参数长度小于等于1,如果 len 也是0,报错,因为没有初始值
if (index >= len) {
throw new TypeError('Reduce of empty array with no initial value');
}
// 此时将数组第一项的值赋值给 value,然后下标++
value = thisArr[index++];
}
// 队列开始
while (index < len) {
if (index in thisArr) {
value = callback(value, thisArr[index], index, thisArr);
}
index++;
}
// 更新 value
return value;
}
var len = arr.length >>> 0 是个什么鬼
>>
是有符号右移
该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位(即符号位)以填充左侧。
9 >> 2
得到 2:
9 (base 10): 00000000000000000000000000001001 (base 2)
--------------------------------
9 >> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)
-9 >> 2
得到 -3,因为符号被保留了。
-9 (base 10): 11111111111111111111111111110111 (base 2)
--------------------------------
-9 >> 2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10)
>>>
是无符号右移
该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符号位变成了 0,所以结果总是非负的。(即便右移 0 个比特,结果也是非负的。)
对于非负数,有符号右移和无符号右移总是返回相同的结果。
但是对于负数,由于右移后左侧总是补0,所以总是得到非负数。
-9 (base 10): 11111111111111111111111111110111 (base 2)
--------------------------------
-9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)
知道了 >>>
是无符号右移,但是右移 0 有什么意义呢??
答案就是:
It doesn't just convert non-Numbers to Number, it converts them to Numbers that can be expressed as 32-bit unsigned ints.
所以,移位操作符做了两件事情,第一将不是 number 的数据转为 number,第二就是将 number 转为无符号的 32bit 数据, 也就是 Uint32 类型。
所以,最上面的代码的意义就是,保证 len 是数字类型,且为正整数,在无意义的情况下取值为0。