- 一篇自己写的promise文章,没写注释,阅读需要一点门槛。
- 做的功能都测试了的,没有发现问题,如有问题的话欢迎评论区留言讨论。
- 转载请注明初次。
<script>
function Promise0(executor) {
let self = this;
self.state = 'padding';
self.resolveValue = '';
self.onResolved = [];
self.onRejected = [];
function resolved(value) {
if (self.state !== 'padding') {
return;
}
self.state = 'resolved';
self.resolveValue = value;
self.onResolved.forEach((fn) => {
fn();
});
}
function rejected(value) {
if (self.state !== 'padding') {
return;
}
self.state = 'rejected';
self.resolveValue = value;
self.onRejected.forEach((fn) => fn());
}
try {
executor(resolved, rejected);
} catch {
executor(rejected);
}
}
Promise0.prototype.then = function (resolve, reject) {
resolve = typeof resolve == 'function' ? resolve : (val) => val;
reject =
typeof reject == 'function'
? reject
: (err) => {
throw err;
};
let self = this;
let res = null;
let Promise2 = new Promise0(function (resolved2, reject2) {
if (self.state == 'resolved') {
setTimeout(() => {
try {
res = resolve(self.resolveValue);
if (typeof res?.then == 'function') {
res.then.call(res, resolved2, reject2);
} else {
resolved2(res);
}
} catch (e) {
reject2(e);
}
}, 0);
} else if (self.state == 'rejected') {
setTimeout(() => {
try {
res = reject(self.resolveValue);
if (typeof res?.then == 'function') {
res.then.call(res, resolved2, reject2);
} else {
resolved2(res);
}
} catch (e) {
reject2(e);
}
}, 0);
} else if (self.state == 'padding') {
self.onResolved.push(() => {
setTimeout(() => {
try {
res = resolve(self.resolveValue);
if (typeof res?.then == 'function') {
res.then.call(res, resolved2, reject2);
} else {
resolved2(res);
}
} catch (e) {
reject2(e);
}
}, 0);
});
self.onRejected.push(() => {
setTimeout(() => {
try {
res = reject(self.resolveValue);
if (typeof res?.then == 'function') {
res.then.call(res, resolved2, reject2);
} else {
resolved2(res);
}
} catch (e) {
reject2(e);
}
}, 0);
});
}
});
return Promise2;
};
Promise0.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
};
Promise0.resolve = function (value) {
return new Promise0(function (resolved, rejected) {
resolved(value);
});
};
Promise0.reject = function (value) {
return new Promise0(function (resolved, rejected) {
rejected(value);
});
};
Promise0.all = function (value) {
return new Promise0(function (resolve, reject) {
let result = [];
let ri = 0;
for (let i = 0; i < value.length; i++) {
let p = value[i];
p.then(function (data) {
result[i] = data;
if (++ri === value.length) {
resolve(result);
}
}, reject);
if (p.state == 'rejected') {
return;
}
}
});
};
Promise0.race = function (value) {
return new Promise0(function (resolve, reject) {
for (let i = 0; i < value.length; i++) {
let p = value[i];
p.then(resolve, reject);
}
});
};
Promise0.any = function (value) {
return new Promise0(function (resolve, reject) {
let pCount = 0;
for (let i = 0; i < value.length; i++) {
let p = value[i];
p.then(resolve, function (v) {
pCount++;
if (pCount === value.length) {
reject(new AggregateError([new Error()], 'All promises were rejected'));
}
});
}
});
};
Promise0.allSettled = function (value) {
return new Promise0(function (resolve, reject) {
let pResult = [];
for (let i = 0; i < value.length; i++) {
let p = value[i];
p.then(
function (v) {
pResult.push({ status: 'fulfilled', value: v });
if (pResult.length === value.length) {
resolve(pResult);
}
},
function (v) {
pResult.push({ status: 'rejected', reason: v });
if (pResult.length === value.length) {
resolve(pResult);
}
}
);
}
});
};
pall1 = new Promise0(function (resolve, reject) {
setTimeout(() => {
reject('reject1');
}, 1000);
});
pall2 = new Promise0(function (resolve, reject) {
setTimeout(() => {
reject('resolve,pall2');
}, 10);
});
pall3 = new Promise0(function (resolve, reject) {
setTimeout(() => {
reject('resolve,pall3');
}, 10);
});
pall4 = pall3.catch(function (v) {
console.log('pall4', v);
return new Promise0(function (resolve, reject) {
reject(11111);
});
});
pany = Promise0.any([pall1, pall2, pall3]);
pany.then(
function (v) {
console.log('pany.then', v);
},
function (v) {
console.log('pany.catch', v);
}
);
</script>