promise解决了什么问题
解决了回调地狱问题, 可以链式调用, 另外提供了Promise.all Promise.race Promise.resolve Promise.reject等方法
1. promise A+规范源码
class myPromise {
constructor(executor) {
this.status = "pending";
this.value = undefined; // 成功的data
this.reason = undefined; // 失败data
this.onResolvedCallbacks = []; // 成功的回调
this.onRejectCallbacks = []; // 失败的回调
let resolve = data => {
if (this.status === "pending") {
this.status = "resolve";
this.value = data;
this.onResolvedCallbacks.forEach(fn => fn()); // 依次执行成功的回调函数
}
};
let reject = data => {
if (this.status === "pending") {
this.status = "reject";
this.reason = data;
this.onRejectCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject); // 函数传参为resolve, reject
} catch (e) {
reject(e);
}
}
then(onFufilled, onRejected) {
onFufilled = typeof onFufilled === "function" ? onFufilled : y => y;
onRejected =
typeof onRejected === "function"
? onRejected
: err => {
throw err;
};
let promise2;
if (this.status === "resolve") {
promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let x = onFufilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
if (this.status === "reject") {
promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
if (this.status === "pending") {
promise2 = new Promise((resolve, reject) => {
this.onResolvedCallbacks.push(
setTimeout(() => {
try {
let x = onFufilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
);
this.onRejectCallbacks.push(
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
);
});
}
}
resolvePromise(promise2, x, resolve, reject) {
//判断x和promise2之间的关系
//因为promise2是上一个promise.then后的返回结果,所以如果相同,会导致下面的.then会是同一个promise2,一直都是,没有尽头
if (x === promise2) {
//相当于promise.then之后return了自己,因为then会等待return后的promise,导致自己等待自己,一直处于等待
return reject(new TypeError("循环引用"));
}
//如果x不是null,是对象或者方法
if (x !== null && (typeof x === "object" || typeof x === "function")) {
//为了判断resolve过的就不用再reject了,(比如有reject和resolve的时候)
let called;
try {
//防止then出现异常,Object.defineProperty
let then = x.then; //取x的then方法可能会取到{then:{}},并没有执行
if (typeof then === "function") {
//我们就认为他是promise,call他,因为then方法中的this来自自己的promise对象
then.call(
x,
y => {
//第一个参数是将x这个promise方法作为this指向,后两个参数分别为成功失败回调
if (called) return;
called = true;
//因为可能promise中还有promise,所以需要递归
resolvePromise(promise2, y, resolve, reject);
},
err => {
if (called) return;
called = true;
//一次错误就直接返回
reject(err);
}
);
} else {
//如果是个普通对象就直接返回resolve作为结果
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
//这里返回的是非函数,非对象的值,就直接放在promise2的resolve中作为结果
resolve(x);
}
}
catch(onRejected) { // catch方法
this.then(null, onRejected);
}
}
2.Promise.resolve
Promise.resolve = function(data) {
return new Promise((resolve, reject) => {
resolve(data);
});
};
3. Promise.reject
Promise.reject = function(data) {
return new Promise((resolve, reject) => {
reject(data);
});
};
4. Promise.all
- 获取所有的promise, 如果全部resolve, 执行then方法, 如果有一个reject,执行catch
Promise.all = function(promise) {
let arr = [];
let i = 0;
function promiseArr(index, data) {
arr[index] = data;
i++;
if (arr.length === i) {
resolve(arr);
}
}
return new Promise((resolve, reject) => {
for (let i = 0; i < promise.length; i++) {
promise[i].then(data => {
promiseArr(i, data);
}, reject);
}
});
};
5.Promise.race
- 哪个先执行完, 直接从then中取值
Promise.race = function(promise) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promise.length; i++) {
promise[i].then(resolve, reject);
}
});
};
6. promise 应用( 使用promise封装ajax)
function ajaxPromise(
url,
methods = "GET",
dataType = "JSON",
async = true
) {
return new Promise((resolve, reject) => {
let XHR = new XMLHttpRequest();
XHR.open(url, methods, async); // 打开方式, url
XHR.responseType = dataType; // 返回文件格式
XHR.onreadystatechange = function() {
if (!/^[23]\d{2}$/.test(XHR.status)) return; // 不是2,3开头三位数字的状态吗, 退出函数
if (XHR.readyState === 4) {
let data = XHR.responseText; // 返回数据
resolve(data);
}
};
XHR.onerror = function(e) {
// 异常处理
reject(e);
};
XHR.send(); // 发送请求
});
}