如果世界上所有的表白都能成功的话,那这个世界就不会存在像我这样的人了。
晚上我回到宿舍将我要表白她的事告诉了室友,室友纷纷当起了劝退师,觉得我压根配不上她,她有太多优质的选择。陷入爱河的我已经听不进任何人的劝阻了,只要有百分之零点一的机会我就想尝试下。于是接下来的几天我一直在计划我的表白了……
终于等到那天,今天的天气额外的宁静清爽,我以各种借口约她晚上去操场走走,起初她并不愿意,在我的死打烂缠下终于答应了。我提前买好了她喜欢的抹茶味奶茶,少糖。现在仍然记得等待时的心情,激动,紧张,充满期待,没一会,她也下来了,我俩并肩像操场走去,我曾在无数个日夜幻想这个场景。
起先我只是和她聊了下最近的生活,我太紧张了,这是我人生中第一次约女孩出来,也是我即将的第一次表白,我一直不能从话题中找一个契合的时机去表白,走着走着已经围绕操场走了2圈了,她也有点想回去的意思,我突然话锋一转,说最近好多人和你表白呀,里面有你喜欢的吗?她说目前还没有让她心动的,她突然也警觉起来,说了句:该不会你要向我表白吧,我从没考虑过和班上人谈恋爱。我赶紧红着脸回答道:不是的,我也才认识你不久,只是觉得你挺优秀的,想和你交个朋友而已….当时我裂了,铁铁们….
回到宿舍我强装着啥事没发生和他们说道表白延后了,我要充分准备下。半夜我哭了,没有声音,只是觉得心里很难受,甚至自己有点莫名其妙。
第一次表白就这样烂在了我心里,还有那封未送出的信。
……..
我如果爱你 绝不学攀援的凌霄花 借你的高枝炫耀自己
我如果爱你 绝不学痴情的鸟儿 为绿荫重复单调的歌曲
……..
Promise用法及手写一个Promise
Promise 简介和基本用法
promise 是一个拥有 then
方法的对象或函数,其行为符合本规范;
promise A+规范我不会详细介绍,感兴趣的可以去promise官网了解。
then
方法接受两个参数 onFulfilled, onRejected
。前者是成功的回调,后者是失败的回调。如果Promise里面执行的是resolve进入onFulfilled
,执行reject进入onRejected
。
人狠话不多,直接上干货了。
new Promise((reslove, reject) => {
console.log(1111);
setTimeout(() => {
console.log('setTimeut', 2222);
reslove(1);
}, 1000);
}).then(
(res) => {
console.log(3333);
},
(err) => console.log(err),
);
复制代码
上图代码的执行结果如下:
Promise.all
使用场景:一次请求多个接口,需要同时拿到里面的信息。
接下来用promise结合setTimeout模拟axios
var promise1 = Promise.resolve('我');
var promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 1000, '不是');
});
var promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 2000, '舔狗');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
复制代码
下图是values的打印结果
Promise.all 弊端
但Promise.all是有弊端的,假如你一次请求5个接口,只要有一个接口请求失败,他将会走到catch
var promise1 = Promise.resolve('我');
var promise2 = new Promise(function (resolve, reject) {
setTimeout(reject, 1000, '不是');
});
var promise3 = new Promise(function (resolve, reject) {
setTimeout(resolve, 2000, '舔狗');
});
Promise.all([promise1, promise2, promise3])
.then(function (values) {
console.log(values);
})
.catch((err) => console.log(err));
复制代码
上面我把promise2 里面换成了reject,它走到catch,下图是打印的err
es11 的 Promise.allSettled 解决了Promise.all弊端
var promise1 = Promise.resolve('我');
var promise2 = new Promise(function (resolve, reject) {
setTimeout(reject, 1000, '不是');
});
var promise3 = new Promise(function (resolve, reject) {
setTimeout(resolve, 2000, '舔狗');
});
Promise.allSettled([promise1, promise2, promise3])
.then(function (values) {
console.log(values);
})
.catch((err) => console.log(err));
复制代码
无论是有失败的请求,他都会走到then里面,并用对象将结果包起来,下图是打印的values
Promise.race
多个请求中,那个先执行就返回该请求的结果,慢的就忽视了
var promise2 = new Promise(function (resolve, reject) {
setTimeout(resolve, 1000, '班花');
});
var promise3 = new Promise(function (resolve, reject) {
setTimeout(resolve, 2000, '舔狗');
});
Promise.all([ promise2, promise3])
.then(function (values) {
console.log(values);
})
复制代码
values的打印结果如下
Promise 值穿透 及如何中断Promise 链式请求
穿透
Promise.resolve(1)
.then(2) // 注意这里
.then(Promise.resolve(3))
.then(console.log); // 输出1 这一步等同 .then((res)=>{console.log(res)})
复制代码
return 一个值修改下一个then里面的value
Promise.resolve(1)
.then(function(){return 2})
.then(Promise.resolve(3))
.then(console.log) // 输出2
复制代码
Promise.resolve(1)
.then(function(){return 2})
.then(function(){return Promise.resolve(3)})
.then(console.log) // 输出3
复制代码
如何中断Promise
中断Promise只有一种方法,那就是让他的状态变为pending
Promise是有三种状态 pending
,fulfilled
,or rejected
const promise = new Promise((resolve, reject) => {
resolve(111);
}).then((res)=>{
console.log(res) //打印111
return 2222
}).then(res=>{
console.log(res) //打印222
return new Promise(()=>{})
}).then(res=>{
console.log(3333) //不会打印,被中断了
})
复制代码
手写Promise
下图是我们常见的业务场景,由浅入深,我们先单纯的实现下面这个例子
new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(1)
resolve(2)
},1000)
}).then(res=>{
console.log(res)
})
复制代码
是不是很简单,x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
就这行需要细品一下,如果卡在了setTimeout,可以看看事件循环机制,如果不懂class的可以看看我的第一文章
//
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class myPromise {
constructor(executor) {
let self = this;
self.status = PENDING;
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks = [];
self.onRejectedCallbacks = [];
let resolve = (value) => {
if (self.status === PENDING) {
self.status = FULFILLED;
self.value = value;
self.onResolvedCallbacks.forEach((fn) => fn());
}
};
executor(resolve);
}
then(onFulfilled, onRejected) {
let self=this
return new myPromise((resolve, reject) => {
if (self.status === 'pending') {
self.onResolvedCallbacks.push(() => {
let x = onFulfilled(self.value);
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
});
self.onRejectedCallbacks.push(() => {
let x = onRejected(self.reason);
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
});
}
});
}
}
复制代码
下图我加入了reject,也完善了then方法里面当状态位fulfilled和rejected。代码量其实并不多….
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class myPromise {
constructor(executor) {
let self = this;
self.status = PENDING;
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks = [];
self.onRejectedCallbacks = [];
let resolve = (value) => {
if (self.status === PENDING) {
self.status = FULFILLED;
self.value = value;
self.onResolvedCallbacks.forEach((fn) => fn());
}
};
let reject = (reason) => {
if (self.status === PENDING) {
self.status = REJECTED;
self.reason = reason;
self.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch {
reject(err);
}
}
then(onFulfilled, onRejected) {
//处理then里面不是回调函数情况
//Promise/A+ 2.2.1 / Promise/A+ 2.2.5 / Promise/A+ 2.2.7.3 / Promise/A+ 2.2.7.4
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v;
onRejected =
typeof onRejected === 'function'
? onRejected
: (err) => {
throw err;
};
let self = this;
return new myPromise((resolve, reject) => {
if (self.status === 'fulfilled') {
setTimeout(() => {
try {
let x = onFulfilled(self.value);
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
} catch (err) {
reject(err);
}
}, 0);
}
if (self.status === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(self.reason);
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
} catch (err) {
reject(err);
}
}, 0);
}
if (self.status === 'pending') {
self.onResolvedCallbacks.push(() => {
setTimeout(() => {
let x = onFulfilled(self.value);
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
}, 0);
});
self.onRejectedCallbacks.push(() => {
setTimeout(() => {
let x = onRejected(self.reason);
x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
}, 0);
});
}
});
}
}
复制代码
仔细分析下onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v;
和 let x = onFulfilled(self.value);
,你就知道下图为啥是这个结果了
Promise.resolve
太简单了吧
static resolve(data){
return new Promise((resolve,reject)=>{ resolve(data); })
}
复制代码
Promise.all
promise.race我就不写了,大家可以参考all想想如何实现
static all(values) {
if (!Array.isArray(values)) {
return new TypeError("请输入一个数组")
}
return new Promise((resolve, reject) => {
let resultArr = [];
let len = 0;
const dealFn = (value, index) => {
resultArr[index] = value;
if (++len === values.length) {
resolve(resultArr)
}
}
for (let i = 0; i < values.length; i++) {
let value = values[i];
//判断value是否还是个promise
if (value && typeof value.then === 'function') {
value.then((value) => {
dealFn(value, i);
}, reject);
} else {
dealFn(value, i);
}
}
});
}
复制代码
总结
我用setTimeout模拟去实现它的延迟执行,没有过多的处理promise整体的容错性,真实的源码用了大量的回调去处理异步执行问题,我只是实现了Promise的回调思想。如果想深入学习Promise的可以去看看官网,我已经晕倒在里面了。只要你认真读懂以上内容,至少不会担心面试官问你promise了
如果喜欢我故事的朋友,第一次看的,可以看看我前面的文章 juejin.cn/post/702429…
最后,麻烦铁子们看完点赞支持下!
作者:舔狗的泪
链接:https://juejin.cn/post/7026896760152784910
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。