promise的状态
为什么会出现Promise?
promise是为了解决回调地狱问题。回调函数本身是很优秀的但是,当业务一多就会造成业务逻辑复杂,业务逻辑复杂造成回调增多,层层嵌套,形成了回调地狱造成代码可观赏性降低,维护成本增高。目前promise是最好的异步处理方案,所以来学一下promise。
回调地狱 => 业务逻辑复杂 => 回调增多 => 可维护性,观赏性降低
promise 有三个状态:pending(等待中), fulfilled(成功), rejected(失败),
打个比方说我有一个承诺十年后去实现,不是现在实现是十年后(异步)
// 定义isPromise :true/false我是否实现了承诺
let isPromise = false;
我许下了一个承诺 => (异步) 比如:'我十年后我会去娶她'
承诺有两个结果:一个是实现了承诺(resolve),一个是没有实现承诺(reject)
// 我许下了一个承诺 => (异步) 比如:'我十年后我会去娶她'
// 承诺有两个结果:实现了承诺(resolve),没有实现承诺(reject)
//定义一个承诺出来
let getPromise = new Promise((resolve, reject) => {
//判断是否完成了承诺,如果完成调用resolve表示成功,如果没有完成承诺调用reject表示拒绝
if (isPromise) {
let promise_z = {
tip: "我记得有一个承诺",
result: "我实现了承诺",
};
// 完成了承诺
resolve(promise_z);
} else {
let err = new Error(
"我有一个承诺,但是因为某些原因我违背了我的承诺,对不起"
);
reject(err);
}
});
接下来测试一下我有没有去实现承诺
let testFn = function () {
getPromise
.then((fulfilled) => {
console.log(fulfilled.tip, fulfilled.result);
})
.catch((rejected) => {
console.log(rejected.message);
});
};
testFn();
如果isPromise=true实现承诺会调用.then方法显示:我记得有一个承诺我实现了承诺
如果isPromise=false没有实现承诺会调用.catch方法显示:我有一个承诺,但是因为某些原因我违背了我的承诺,对不起
所以通过上面会发现
打个比方 :你和你的女朋友在交往,一旦你承诺你后面会娶她,就只有两个结果,在过程中是女方等待(pending)的过程,但是她最后只能得到你的一种回复要么是成功(fulfilled),要么是失败(rejected),没有可能是你没说过这句话,说出去的话泼出去的水一样,收不回来。
promise是异步它的状态无法改变因为最开始的状态是pending(等待中),一旦执行就只有一个结果成功(fulfilled)或者失败(rejected)
应用层promise的链式调用
接下来再接着上面的例子写,打个比方你要娶你的女朋友,那么你们会结婚,但是如果你不想娶你的女朋友你们就不会结婚
还是和刚才一样
先承诺会去娶她
// isPromise :true/false我是否实现了承诺
let isPromise = true;
// 我许下了一个承诺 => (异步) 比如:'我十年后我会去娶她'
// 承诺有两个结果:实现了承诺(resolve),没有实现承诺(reject)
let getPromise = new Promise((resolve, reject) => {
if (isPromise) {
let promise_z = {
tip: "我记得有一个承诺",
result: "我实现了承诺",
};
// 完成了承诺
resolve(promise_z);
} else {
let err = new Error(
"我有一个承诺,但是因为某些原因我违背了我的承诺,对不起"
);
reject(err);
}
});
然后再声明一个你们会结婚,前提是你记得承诺会去娶她,里面声明了一个msg是消息
// 我在实现承诺说要娶她后,才会和她结婚,如果不说娶她,就不会和她结婚
let getMarry = (promise_z) => {
let marry = {
tip: "我和她说我要娶她",
result: "我们要结婚了",
};
let msg = {
message: marry.tip + marry.result,
marry: marry,
promise_z: promise_z,
};
return Promise.resolve(msg);
};
其次再测试一下有没有去实现承诺,在第一个then里面传了一个promise对象,当第一个承诺实现后,会接着嗲用第二个承诺,因为是链式调用最后先得到结婚,然后再得到实现了之前的承诺
let testFn2 = () => {
getPromise
.then(getMarry) //传的是promise对象
.then((fulfilled) => {
console.log(fulfilled);
})
.catch((rejected) => {
console.log(rejected.message);
});
};
testFn2();
手写Promise的链式调用 ES5
从pending到fulfilled
promise的状态从pending(等待)=》成功通过resolve返回值 =》状态变为 fulfilled(成功)
从pending到rejected
promise的状态从pending(等待)=》失败通过reject抛出错误 =》状态变为 rejected(失败)
从四个方面入手
1、基本结构
2、then方法
3、支持异步
4、链式调用
<script>
//1、基本结构
// excutor 用来指向的
function myPromise(excutor) {
let self = this;
self.status = "pending"; //状态
self.value = null; //成功之后,返回数据
self.reason = null; //失败的原因
//7、解决异步问题 =》暂存区
// 发布订阅者模式先将相关的值存起来,当状态变化的时候再将里面的状态一个一个的取出
self.onFulfilledCallbacks = [];
self.onRejectedCallbacks = [];
// 返回成功的结果
function resolve(value) {
// 5.1 更改成功状态
if (self.status === "pending") {
self.value = value; //保存成功结果
self.status = "fulfilled";
// 9、状态改变 =》 依次取出
self.onFulfilledCallbacks.forEach((item) => item(value));
}
}
// 返回失败的原因
function reject(reason) {
// 5.2更改失败状态
if (self.status === "pending") {
self.reason = reason; //失败原因
self.status = "rejected";
// 9、状态改变 =》 依次取出
self.onRejectedCallbacks.forEach((item) => item(reason));
}
}
// 3、excutor => 立即执行
// excutor && excutor(resolve, reject);
// try catch 是为了做容错处理
try {
excutor(resolve, reject);
} catch (err) {
reject(err);
}
}
// 2、then()方法 放在原型上 不管成功还是失败都会走进来
myPromise.prototype.then = function (onFulfilled, onRejected) {
// 6. 确保传进来的是方法,如果不是,定义一个方法
onFulfilled =
typeof onFulfilled === "function"
? onFulfilled
: function (data) {
resolve(data);
};
// 判断函数是不是方法(类型是不是 function)如果不是就写个方法 抛出错误
onRejected =
typeof onRejected === "function"
? onRejected
: function (err) {
throw err;
};
let self = this;
//8、 暂存回调函数
if (self.status === "pending") {
self.onFulfilledCallbacks.push(onFulfilled);
self.onRejectedCallbacks.push(onRejected);
}
// if (self.status === "fulfilled") {
// return new myPromise((resolve, reject) => {
// try {
// let x = onFulfilled(selef.value);
// x instanceof myPromise ? x.then(resolv, reject) : resolve(x);
// } catch (err) {
// reject(err);
// }
// });
// }
};
//3、初级嗲用
let demo = new myPromise((resolve, reject) => {
console.log("111");
// 异步任务
// 如果没写相关代码,在异步任务中执行resolve函数是没用的因为状态没变更.then方法没法调用,所以需要用到发布订阅者模式
setTimeout(() => {
resolve(222);
}, 2000);
});
demo.then((data) => console.log(data));
</script>
上面代码,关于链式调用的还没写,其它的完成了