手写Promise
1、定义整体结构
(function (window) {
// excutor: 内部同步执行的函数 (resolve, reject) => {}
function Promise(excutor) {}
// 为promise指定成功/失败的回调,返新的promise
Promise.prototype.then = function (onResolved, onRejected) {};
// 为promise指定失败的回调,是then(null, onRejected)的语法糖
Promise.prototype.catch = function (onRejected) {};
// 返回一个指定了成功value的promis
Promise.resolve = function (value) {};
// 返回一个指定了失败reason的promise
Promise.reject = function (reason) {};
// 返回一个promise, 只有promises中所有promise都成功时, 才最终成功, 只要有一个失败就直接失败
Promise.all = function (promises) {};
// 返回一个promise, 一旦某个promise解决或拒绝, 返回的promise就会解决或拒绝。
Promise.race = function (promises) {};
// 暴露构造函数
window.Promise = Promise;
})(window);
2、Promise 构造函数的实现
// excutor: 内部同步执行的函数 (resolve, reject) => {}
function Promise(excutor) {
const self = this;
// 状态值, 初始状态为 pending, 成功了变为resolved, 失败了变为 rejected
self.status = "pending";
// 用来保存成功 value 或失败 reason 的属性
self.data = undefined;
// 用来保存所有待调用的包含 onResolved 和 onRejected 回调函数的对象的数组
self.callbacks = [];
/*异步处理成功后应该调用的函数
value: 将交给 onResolve()的成功数据
*/
function resolve(value) {
if (self.status !== "pending") {
// 如果当前不是 pending, 直接结束
return;
}
// 立即更新状态, 保存数据
self.status = "resolved";
self.data = value;
// 异步调用所有待处理的 onResolved 成功回调函数
if (self.callbacks.length > 0) {
setTimeout(() => {
self.callbacks.forEach((obj) => {
obj.onResolved(value);
});
});
}
}
/*异步处理失败后应该调用的函数
reason: 将交给 onRejected()的失败数据
*/
function reject(reason) {
if (self.status !== "pending") {
// 如果当前不是 pending, 直接结束
return;
}
// 立即更新状态, 保存数据
self.status = "rejected";
self.data = reason;
// 异步调用所有待处理的onResolved成功回调,同步代码length为0,resolve被包裹在定时器中等异步情况才不为0
setTimeout(() => {
self.callbacks.forEach((obj) => {
obj.onRejected(reason);
});
});
}
try {
// 立即同步调用 excutor()处理
excutor(resolve, reject);
} catch (error) {
// 如果出了异常, 直接失败
reject(error);
}
}
3、promise.then()/catch()的实现
// 为promise指定成功/失败的回调,返新的promise
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 如果 onResolved/onRejected 不是函数, 可它指定一个默认的函数
onResolved =
// 指定返回的 promise 为一个成功状态, 结果值为 value
typeof onResolved === "function" ? onResolved : (value) => value;
onRejected =
// 指定返回的 promise 为一个失败状态, 结果值为 reason
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
// 返回一个新的 promise 对象
return new Promise((resolve, reject) => {
/*专门抽取的用来处理 promise 成功/失败结果的函数
callback: 成功/失败的回调函数
*/
function handle(callback) {
// 1. 抛出异常 ===> 返回的 promise 变为 rejected
try {
const x = callback(self.data);
// 2. 返回一个新的 promise ===> 得到新的 promise 的结果值作为返回的promise 的结果值
if (x instanceof Promise) {
// 一旦 x 成功了, resolve(value), 一旦 x失败了: reject(reason);
x.then(resolve, reject);
} else {
// 3. 返回一个一般值(undefined) ===> 将这个值作为返回的 promise 的成功值;
resolve(x);
}
} catch (error) {
reject(error);
}
}
if (self.status === "resolved") {
// 当前 promise 已经成功了
setTimeout(() => {
handle(onResolved);
});
} else if (self.status === "rejected") {
// 当前 promise 已经失败了
setTimeout(() => {
handle(onRejected);
});
} else {
// 当前 promise 还未确定 pending (例:resolve被包裹在定时器中,执行到then,status为pending)
// 将 onResolved 和 onRejected 保存起来
self.callbacks.push({
onResolved(value) {
handle(onResolved);
},
onRejected(reason) {
handle(onRejected);
},
});
}
});
};
// 为promise指定失败的回调,是then(null, onRejected)的语法糖
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
};
4、Promise.resolve()/reject()的实现
// 返回一个指定了成功value的promise
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
};
// 返回一个指定了失败reason的promise
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
};
5、Promise.all/race()的实现
// 返回一个promise, 只有promises中所有promise都成功时, 才最终成功, 只要有一个失败就直接失败
Promise.all = function (promises) {
// 返回一个新的 promise
return new Promise((resolve, reject) => {
// 已成功的数量
let resolvedCount = 0;
// 待处理的 promises 数组的长度
const promisesLength = promises.length;
// 准备一个保存成功值的数组
const values = new Array(promisesLength);
// 遍历每个待处理的 promise
for (let i = 0; i < promisesLength; i++) {
// promises 中元素可能不是一个数组, 需要用 resolve 包装一下
Promise.resolve(promises[i]).then(
(value) => {
// 成功当前 promise 成功的值到对应的下标
values[i] = value;
// 成功的数量加 1
resolvedCount++;
// 一旦全部成功
if (resolvedCount === promisesLength) {
// 将所有成功值的数组作为返回 promise 对象的成功结果值
resolve(values);
}
},
(reason) => {
// 一旦有一个promise产生了失败结果值, 将其作为返回promise对象的失败结果值;
reject(reason);
}
);
}
});
};
// 返回一个promise, 一旦某个promise解决或拒绝, 返回的promise就会解决或拒绝。
Promise.race = function (promises) {
// 返回新的 promise 对象
return new Promise((resolve, reject) => {
// 遍历所有 promise
for (var i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(
(value) => {
// 只要有一个成功了, 返回的 promise 就成功了
resolve(value);
},
(reason) => {
// 只要有一个失败了, 返回的结果就失败了
reject(reason);
}
);
}
});
};
扩展:Promise.resolveDelay()/rejectDelay()的实现
// 返回一个延迟指定时间才确定结果的 promise 对象
Promise.resolveDelay = function (value, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (value instanceof Promise) {
// 如果 value 是一个 promise, 取这个promise 的结果值作为返回的 promise 的结果值
value.then(resolve, reject); // 如果 value 成功, 调用resolve(val), 如果 value 失败了, 调用 reject(reason)
} else {
resolve(value);
}
}, time);
});
};
// 返回一个延迟指定时间才失败的 Promise 对象。
Promise.rejectDelay = function (reason, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(reason);
}, time);
});
};
测试
<script>
// 如果是一般值, p1成功, value就是这个值
const p1 = Promise.resolve(2);
// 如果是成功的promise, p2成功, value是这个promise的value
const p2 = Promise.resolve(Promise.resolve(3));
// 如果是失败的promise, p3失败, reason是这个promise的reason
const p3 = Promise.resolve(Promise.reject(4));
p1.then((value) => {
console.log("p1", value);
});
p2.then((value) => {
console.log("p2", value);
});
p3.catch((reason) => {
console.log("p3", reason);
});
// const p4 = new Promise((resolve) => {
// setTimeout(() => {
// resolve(5)
// }, 1000);
// })
const p4 = Promise.resolveDelay(5, 1000);
const p5 = Promise.reject(6);
const pAll = Promise.all([p4, 7, p1, p2]);
pAll.then(
(values) => {
console.log("race onResolved()", values);
},
(reason) => {
console.log("race onRejected()", reason);
}
);
// const pRace = Promise.race([p4, 7, p5, p2, p3])
// pRace.then(
// value => {
// console.log('race onResolved()', value)
// },
// reason => {
// console.log('race onRejected()', reason)
// }
// )
const p6 = Promise.resolveDelay(66, 2000);
const p7 = Promise.rejectDelay(77, 3000);
p6.then((value) => {
console.log("p6", value);
});
p7.catch((reason) => {
console.log("p7", reason);
});
</script>

Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.
1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino
我一直梦想, 看到你们相册那样的地方。真棒。
我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。
我热爱这样的想法, 去那么多国家。真的很鼓舞。
能感受到热爱。继续保持 感受。
我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。
1
1
1