-
Notifications
You must be signed in to change notification settings - Fork 834
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第十八题:请实现 Promise.all #23
Comments
Promise.all = function(arr) {
if(!Array.isArray(arr)) {
throw new Error('参数必须是数组')
}
return new Promise((resolve, reject) => {
const list = []
arr.forEach(item => {
this.resolve(item).then((value) => {
list.push(value)
if(list.length === arr.length) {
resolve(list)
}
}, (err)=> {
reject(err)
})
})
})
} |
Promise.All = function (arg) {
if (!Array.isArray(arg)) {
return Promise.reject(new Error('参数必须是数组'))
}
return new Promise((resolve, reject) => {
let count = 0;
const totalCount = arg.length
const results = []
arg.forEach((item, index) => {
const ret = item?.then ? item : Promise.resolve(item)
ret.then(result => {
count++
results[index] = result
if (count === totalCount) {
resolve(results)
}
}).catch(error => {
reject(error)
})
})
})
}
const request = (data) => new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.9) {
resolve(data)
} else {
reject(data)
}
}, 2000 * Math.random());
})
Promise.All([1, 2, 3, request(4)]).then(ret => {
console.log("ret2", ret)
}).catch(error => {
console.error("error2", error)
})
// ret2 (4) [1, 2, 3, 4]
Promise.All(new Array(10).fill(null).map((e, i) => request(i))).then(ret => {
console.log("ret", ret)
}).catch(error => {
console.error("error", error)
})
// ret (10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] |
@learnRy 返回结果顺序不对 |
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";
class MyPromise {
constructor(callback) {
this.status = PENDING;
this.value = null;
this.resolvedCB = [];
this.rejectedCB = [];
callback(this.resolve.bind(this), this.reject.bind(this));
}
resolve(data) {
this.value = data;
this.status = RESOLVED;
this.resolvedCB.forEach((cb) => {
this.value = cb(this.value);
});
this.resolvedCB = [];
}
reject(data) {
this.value = data;
this.status = REJECTED;
this.rejectedCB.forEach((cb) => {
this.value = cb(this.value);
});
this.rejectedCB = [];
}
then(handleResolved, handleRejected) {
handleResolved && this.resolvedCB.push(handleResolved);
handleRejected && this.rejectedCB.push(handleRejected);
if (this.status === RESOLVED) {
this.resolvedCB.forEach((cb) => {
this.value = cb(this.value);
});
this.resolvedCB = [];
}
if (this.status === REJECTED) {
this.rejectedCB.forEach((cb) => {
this.value = cb(this.value);
});
this.rejectedCB = [];
}
}
}
MyPromise.all = function (promises) {
const allData = [];
return new MyPromise((resolve, reject) => {
const run = () => {
if (promises.length === 0) return;
const promise = promises.shift();
if (promise) {
promise.then((data) => {
allData.push(data);
if (promises.length === 0) {
resolve(allData);
} else {
run();
}
});
}
};
run();
});
};
// test
const a = new MyPromise((resolve) => {
setTimeout(() => resolve("a"), 200);
});
const b = new MyPromise((resolve) => {
setTimeout(() => resolve("b"), 800);
});
const c = new MyPromise((resolve) => {
setTimeout(() => resolve("c"), 100);
});
MyPromise.all([a, b, c]).then((data) => console.log("allData", data));
// ["a", "b", "c"] |
这个MyPromise不符合Promise/A+规范 |
function _all(arr) {
//数组类型检查
if (!Array.isArray(arr)) {
throw new TypeError('is not Array')
}
return new Promise(function (reslove, reject) {
try {
let result = []
for (let item of arr) {
//检查实例是否为Promises实例
if (Object.prototype.toString.call(item).indexOf("Promise") == -1) {
//没有的话返回当前值(为了保证按顺序执行,自己封装一个Promise实例)
item = new Promise(function (reslove, reject) {
reslove(item)
})
}
item.then((res, err) => {
if (err) {
throw new Error(err)
} else {
result.push(res)
if (arr.indexOf(item) == arr.length - 1) {
reslove(result)
}
}
})
}
} catch (error) {
reject(error)
}
})
}
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
const promise4 = function name(params) {
};
_all([promise2, promise1, promise4,promise3]).then(res => {
console.log(res, 'cc');
})
//[ 42, 3, [Function: name], 'foo' ] cc |
function promiseAll(list) {
if (!Array.isArray(list)) {
throw new Error('参数错误')
}
const result = []
const n = list.length
let successCount = 0
list.forEach((item, index) => {
item.then(res => {
result[index] = res
successCount++
if (n === successCount) {
return Promise.resolve(result)
}
}).catch(e => {
return Promise.reject(e)
})
})
} |
// 请实现 Promise.all
Promise.all = (arr) => {
const length = arr.length;
const result = [];
let count = 0;
return new Promise((resolve, reject) => {
arr.forEach((item, index) => {
if (item instanceof Promise) {
item.then(
(res) => {
result[index] = res;
count += 1;
if (count === length) resolve(result);
},
(error) => {
reject(error);
}
);
} else {
result[index] = item;
count += 1;
if (count === length) resolve(result);
}
});
});
}; |
代码实现 Promise.myAll = function (promises) {
let count = 0;
return new Promise((resolve, reject) => {
let result = new Array(promises.length);
for (let i = 0; i < promises.length; i += 1) {
const promise = promises[i];
if (promise instanceof Promise) {
promise
.then((res) => {
result[i] = res;
count += 1;
if (count === promises.length) {
resolve(result);
}
})
.catch((err) => {
reject(err);
});
} else {
result[i] = promise;
count += 1;
if (count === promises.length) {
resolve(result);
}
}
}
});
}; 测试用例 const p1 = new Promise((resolve) => {
setTimeout(() => {
resolve('hello');
}, 1000);
});
const p2 = new Promise((resolve) => {
setTimeout(() => {
resolve('world');
}, 500);
});
const p3 = 999;
const p4 = Promise.reject('this is an error');
Promise.myAll([p1, p2, p3]).then((res) => {
console.log(`res: `, res);
});
// res: [ 'hello', 'world', 999 ]
Promise.myAll([p1, p2, p3, p4])
.then((res) => {
console.log(`res: `, res);
})
.catch((error) => {
console.log(`error: `, error);
})
// error: this is an error |
Promise.all思路:
Promise.myAll = function (array) {
if (!Array.isArray(array)) {
return Promise.reject(new Error("Error: The params must be an Array"));
}
return new Promise((resolve, reject) => {
let count = 0;
let result = [];
array.forEach((element, index) => {
const isPromise = element instanceof Promise;
const promise = isPromise ? element : Promise.resolve(element);
promise
.then((res) => {
count = count + 1;
result[index] = res;
if (array.length === count) {
resolve(result);
}
})
.catch((error) => reject(error));
});
});
}; Tips:
|
刚好最近试着封装了下promise
|
Promise.MyAll = function(pArr) {
const length = pArr.length
if (!Array.isArray(pArr)) {
throw new Error('参数必须是数组')
}
return new Promise((resolve, reject) => {
let res = Array(length).fill(), count = 0
pArr.forEach((p, idx) => {
p = p instanceof Promise ? p : Promise.resolve(p)
p.then((data) => {
count++
res[idx] = data
if (count === length) {
resolve(res)
}
}).catch(err => {
reject(err)
})
})
})
}
function fn(data) {
return new Promise((resolve, reject) => {
Math.random() < 0.7 ? resolve(data) : reject(`${data}`)
}, Math.random() * 2000)
}
Promise.MyAll([0, fn(1), fn(3), 3]).then((data) => {
console.log('data', data)
}).catch((err) => {
console.log('err', err)
}) |
实现一个Promise.all 功能Promise.all 是传入xxx 返回xxxPromise.all() 方法接收一个promise的 iterable 类型(注:Array,Map,Set都属于ES6的iterable类型)的输入,并且只返回一个Promise实例, 那个输入的所有promise的resolve回调的结果是一个数组。这个Promise的resolve回调执行是在所有输入的promise的resolve回调都结束,或者输入的 iterable 里没有 promise 了的时候。它的reject回调执行是,只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。 var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
reject('reject');
});
Promise.all([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
//From console://"reject" 具体实现方式// 判断该数组中的内容是否为 Promise
const isPromise = obj =>
!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'
function promiseAll(target) {
// 判断传入的是否为 iterable 类型的数据
if (Array.from(target) instanceof Array) {
// 核心逻辑 按照数组的顺序,依次执行并返回数组中
return new Promise(async function (resolve, reject) {
try {
let result = []; // 保存最后返回结果的数组
for (let i = 0; i < target.length; i++) {
if (isPromise(target[i])) { // 判断是否为 Promise类型
// 如果其中一个 Promise 出现错误了 直接就返回 不再执行后面的内容
const answer = await target[i];
result.push(answer);
} else {
result.push(target[i]); // 直接存到数组中
}
}
resolve(result);
} catch (err) {
reject(err);
}
})
} else {
throw new TypeError(typeof target + target + 'is not iterable (cannot read property Symbol(Symbol.iterator))'); // 返回类型错误 例如 boolean 类型不能进行枚举
}
}
const p1 = Promise.reject(3);
const p2 = 42;
const p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
promiseAll([p1, p2, p3]).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
}) 疑问
|
|
const p1 = new Promise((resolve, reject) => {
let num = 1;
setTimeout(() => {
resolve(num)
}, 3000);
});
const p2 = 3;
const p3 = Promise.resolve(4);
const p4 = setTimeout(() => {
console.log('sdffsd')
}, 2000);
const p5 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(5)
}, 3000);
})
Promise.myAll = (args) => {
if(!Array.isArray(args)){
throw new Error('参数必须是数组')
}
return new Promise((resolve, reject) => {
let result = [];
for(let i = 0, len = args.length; i < len; i++) {
Promise.resolve(args[i]).then(res => {
result.push(res);
if(result.length === len) {
resolve(result)
}
}, (err) => {
reject(err);
})
}
});
}
const p6 = new Promise((resolve, reject) => {
let num = 1;
setTimeout(() => {
if(num === 1) reject('num 不能为1')
}, 3000);
});
Promise.myAll([p1,p2, p3, p4, p5]).then(res => {
console.log(res, 'promise all resolve')
}, (err) => {
console.log(err, 'promise all rejected')
});
// 执行结果
// Array(5) [3, 4, 87, 1, 5] "promise all resolve"
Promise.myAll([p2, p3, p4, p5, p6]).then(res => {
console.log(res, 'promise all resolve')
}, (err) => {
console.log(err, 'promise all rejected')
});
// 执行结果
// num 不能为1 promise all rejected |
Promise.myAll = function (arr) {
if (!Array.isArray(arr)) {
throw new Error("参数必须为数组");
}
return new Promise((resolve, reject) => {
let result = [];
arr.forEach((p, index) => {
p = p.then ? p : Promise.resolve(p)
p.then((res) => {
result[index] = res;
if (result.length === arr.length) {
resolve(result);
}
}).catch((err) => reject(err));
});
});
}; |
const isIterable = (obj) => {
return obj != null && typeof obj[Symbol.iterator] === "function";
};
Promise.all1 = function (arr) {
if (!isIterable(arr)) {
throw new TypeError(typeof arr + " " + arr + " " + "is not iterable");
}
return new Promise((resolve, reject) => {
let resolvedArr = [];
let resolvedCount = 0;
for (let [index, value] of arr.entries()) {
((index, value) => {
Promise.resolve(value).then(
(res) => {
resolvedCount++;
resolvedArr[index] = res;
if (resolvedCount === arr.length) {
resolve(resolvedArr);
}
},
(err) => {
reject(err);
}
);
})(index, value);
}
});
};
let p1 = Promise.resolve(3);
let p2 = 1337;
let p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "foo");
});
let p = Promise.all1([p1, p2, p3]).then((values) => {
console.log("values", values); // [3, 1337, "foo"]
}); |
function myPromiseAll(params) { |
const PENDING ='PENDING'; class PromiseA = function(executor) {
const resolve = (value) => { const reject = (reason) => { // 同步 executor调用 then(onFulFilled, onRejected) {
} new PromiseA ((resolve, reject) =>{ 只能实现一个 PromiseA , PromiseAll 暂时无法实现 |
Promise._all = function(promiseList = []) {
if(!Array.isArray(promiseList)) {
throw new TypeError('参数必须是数组')
}
return new Promise((resolve, reject) => {
let count = 0;
let res = []
promiseList.forEach((promise, index) => {
Promise.resolve(promise).then((value) => {
res[index] = value
count++
if(count === promiseList.length) {
resolve(res)
}
}, reject)
})
});
};
Promise._all([1, Promise.resolve(4)]).then(val => {
console.log('ok', val) // ok [ 1, 4 ]
}).catch(err => {
console.log('error', err)
})
Promise._all([1, Promise.resolve(4), Promise.reject(new Error('error'))]).then(val => {
console.log('ok', val)
}).catch(err => {
console.log('error', err) // error Error: error
})
|
|
let obj = {
a: 1,
b: 2,
[Symbol.iterator]: function*(){
yield 'iterator obj 1';
yield 'iterator obj 2';
yield 'iterator obj 3';
}
}
Promise.myAll = function(iterator){
return new Promise((resolve, reject) => {
let arr = []
let total = 0
let isDone = false
function success(res){
if(isDone){
return
}
arr.push(res)
total--
if(total <= 0) {
isDone = true
resolve(arr)
}
}
function faild(e){
if(isDone){
return
}
isDone = true
reject(e)
}
// 如果不是可迭代对象自会抛出错误
// 要兼容es6以下版本的需要判断是否为数组、字符串?
for(let value of iterator){
total++
Promise.resolve(value).then(success, faild)
}
})
}
testPromiseAll('abcdef')
testPromiseAll([1,2,3,4,5])
testPromiseAll(new Map([[1, 'Map1'], [2,'Map2']]))
testPromiseAll(new Set(['set1', 'set2']))
testPromiseAll([1,2,3,4,5])
testPromiseAll([sleep(100), sleep(200)])
testPromiseAll([sleep(100), sleep(200, true)])
testPromiseAll(obj)
function testPromiseAll(iterotor){
Promise.all(iterotor).then(res => {
console.log('Promise.all ', res)
}).catch(e => {
console.log('Promise.all ', e);
})
Promise.myAll(iterotor).then(res => {
console.log('Promise.myAll error', res);
}).catch(e => {
console.log('Promise.myAll error', e);
})
}
function sleep(time = 500, isFaild = false){
return new Promise((resolve, reject) => {
setTimeout(() => {
isFaild ? reject(new Error('mock error' + time)) : resolve('time: ' + time)
}, time)
})
} |
|
myPromise.prototype.all = function(params) {
if (!(params instanceof Array)) {
throw new Error('错误');
}
return new Promise((resolve, reject) => {
let res = [];
for (let i = 0; i < params.length; i++) {
params[i].then((data) => {
res[i] = data;
if (res.length === params.length) {
resolve(res);
}
}).catch((err) => {
reject(err);
});
}
});
} |
// 传入一个数组,等数组的全部成功之后,返回一个Promise对象,成功回调全部返回的数组
Promise.myAll(arr) {
// 用于接收所有返回值
let result = [];
// 每次调用addData 这个index会加1 用index和传入数组的length比较 来解决异步函数的问题
let index = 0;
return new MyPromise((resolve, reject) => {
// 将数组中每一项添加到result数组中
function addData(key, value) {
result[key] = value;
index++;
if (index === arr.length) {
resolve(result);
}
}
for (let index = 0; index < arr.length; index++) {
let current = arr[index];
// 需要判断数组中的每一项是promise还是普通值
if (current instanceof MyPromise) {
// promise 对象
current.then(
(value) => addData(i, value),
(reason) => reject(reason)
);
} else {
//普通值
addData(i, current);
}
}
});
} |
1、入参校验
|
function _PromissAll(promises) {
if (!Array.isArray(promises)) {
throw new TypeError('argument must be a array');
}
return new Promise((resolve, reject) => {
let promiseCount = 0;
let promiseNum = promises.length;
let result = [];
for (let i = 0; i < promiseNum; i++) {
Promise.resolve(promises[i])
.then(res => {
promiseCount++;
result[i] = res;
if (promiseCount === promiseNum) {
return resolve(result);
}
})
.catch(e => {
reject(e);
});
}
});
} |
Promise.all = function (promiseArr) {
if (!Array.isArray(promiseArr)) {
throw new TypeError('not array');
}
return new Promise((resolve, reject) => {
let i = 0;
let result = [];
let len = promiseArr.length;
let count = len;
function resolver(index) {
return function (value) {
resolveAll(index, value);
}
}
function rejecter(reason) {
reject(reason);
}
function resolveAll(index, value) {
result[index] = value;
if (--count === 0) {
resolve(result);
}
}
for (; i < len; i++) {
promiseArr[i].then(resolver(i), rejecter);
}
})
} |
function PromiseAll(promises) {
return new Promise((resolve, reject) => {
let resultCount = 0
let promiseLen = Promise.length // 传入的promise个数
let results = new Array(promiseLen) // 存放返回结果
for (let i = 0; i < promiseLen; i++) {
promises[i].then(value => {
resultCount++;
results[i] = value
if (resultCount === promiseLen) {
return resolve(results)
}
}, error => {
reject(error)
})
}
})
} |
|
|
// 请实现 Promise.all
Promise.all2 = function (promises) {
if (!Array.isArray(promises)) {
throw new Error('all 中必须是数组')
}
return new Promise((resolve, reject) => {
let resolvedCount = 0;
const resolvedValues = new Array(promises.length)
const promisesNum = promises.length
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(res => {
resolvedCount++;
resolvedValues[i] = res
if (resolvedCount === promisesNum) {
resolve(resolvedValues)
}
}, reason => {
reject(reason)
})
}
})
}
function timer(time, val) {
return new Promise((resolve, reject) => {
console.time(val)
setTimeout(() => {
console.timeEnd(val)
resolve(val)
}, time);
})
}
var promises = [
timer(1200, 'xiaoming'),
timer(3000, 'xiaohong'),
timer(2000, 'xiaohuang'),
timer(1500, 'xiaosan'),
3]
console.time('all')
Promise.all2(promises).then(arr => {
console.timeEnd('all')
console.log(arr)
})
// xiaoming: 1202.260986328125 ms
// xiaosan: 1501.62109375 ms
// xiaohuang: 2008.06005859375 ms
// xiaohong: 3000.2119140625 ms
// all: 3001.406982421875 ms
// ["xiaoming", "xiaohong", "xiaohuang", "xiaosan", 3] |
请实现
Promise.all
去答题
新建了一个大厂真题每日打卡群,有意愿学习打卡的再进,请备注打卡。
The text was updated successfully, but these errors were encountered: