写法不同
ES5 正常写法:
getAjax(url,(res)->{})
ES6 Promise
get(rul).then((res)=>{})
async await
(async ()=>{
let res = await get(rul)
})()
ES5 写法和 promise 写法,主要区别在于写法的不同,可以让 ES5 写法中的回调函数划分出去到
.then
函数中去执行,使得代码更加灵活。async 和 promise 的区别,主要在于 async 是 Promise 的语法糖,这种形式的写法在底层编译之后,会自动转化成 Promise,本质是 Promise。
Promise 实现原理
Promise 需要实现的功能
var p1 = new WJPromise(fn);
p1.then(function (res) {
console.log("这是成功做的事情");
});
p1.catch(function (res) {
console.log("这是失败要做的事情");
});
p1 promise 对象发送了异步操作,必然会有一个未来事件,在未来要执行。这个过程有传入的函数对象 fn 执行。函数 fn 中必然有成功执行的函数和失败执行的函数。
1、创建类构造对象。
class WJPromise {
constructor(fn) {
//将成功的事件函数集成在 successLsit 数组中
this.successList = [];
//将失败的事件函数集成在 fialList 数组中
this.failList = [];
//pengding fullfiled rejected
this.state = "pending";
//传入的函数对象,(异步操作的函数内容)
fn(this.resolveFn.bind(this), this.rejectFn.bind(this));
}
}
构造函数作用:
- 声明成功函数放置的数组对象;
- 声明失败函数放置的数组对象;
- 定义初始化状态;
- 调用传入进来执行异步内容的函数(在未来有成功的结果时,调用传入进去的成功函数;在未来失败时,调用传入进行的失败函数);
2、传入成功或者失败时需要调用的函数
class WJPromise {
constructor(fn) {
//将成功的事件函数集成在 successLsit 数组中
this.successList = [];
//将失败的事件函数集成在 fialList 数组中
this.failList = [];
//pengding fullfiled rejected
this.state = "pending";
//传入的函数对象,(异步操作的函数内容)
fn(this.resolveFn.bind(this), this.rejectFn.bind(this));
}
then(successFn, failFn) {
if (typeof successFn == "function") {
this.successList.push(successFn);
}
if (typeof failFn == "function") {
this.failList.push(failFn);
}
}
catch(failFn) {
if (typeof failFn == "function") {
this.failList.push(failFn);
}
}
}
- 将成功和失败的函数,传入成功和失败的数组中。
3、定义调用成功和失败的函数
class WJPromise {
constructor(fn) {
//将成功的事件函数集成在 successLsit 数组中
this.successList = [];
//将失败的事件函数集成在 fialList 数组中
this.failList = [];
//pengding fullfiled rejected
this.state = "pending";
//传入的函数对象,(异步操作的函数内容)
fn(this.resolveFn.bind(this), this.rejectFn.bind(this));
}
then(successFn, failFn) {
if (typeof successFn == "function") {
this.successList.push(successFn);
}
if (typeof failFn == "function") {
this.failList.push(failFn);
}
}
catch(failFn) {
if (typeof failFn == "function") {
this.failList.push(failFn);
}
}
resolveFn(res) {
this.state = "fullfilled";
this.successList.forEach(function (item, index) {
//将成功的事件循环调用
item(res);
});
}
regectFn(res) {
this.state = "reject";
//注册到失败的所有事件进行调用
this.failList.forEach(function (item, index) {
item(res);
});
throw Error(res);
}
}
成功时调用成功数组里所有的函数,失败时调用失败数组里所有的函数。
应用
典型的异步读写回调操作:
fs.readFile(path, { flag: "r", encoding: "utf-8" }, function (err, data) {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
封装成 Promise
new Promise(function (resolve, reject) {
fs.readFile(path, { flag: "r", encoding: "utf-8" }, function (err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
封装一下,便于调用:
function fsRead(path) {
new Promise(function (resolve, reject) {
fs.readFile(path, { flag: "r", encoding: "utf-8" }, function (err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
使用:
p1 = fsRead(path); //就可以得到 promise 对象
p1.then(function (data) {
console.log("输出数据:", data);
});
async await 写法:
let data = await fsRead(path); //相当于 fsRead(path).then(function(data){})
当然,这是需要在异步函数中使用的:
(async () => {
let data = await fsRead(path);
})();
异步 async 函数调用之后也是一个 promise 对象。
async function test() {
let data = await fsRead(path);
return data;
}
let a = test(); //这里的 a 是一个 promise 对象
a.then(function (data) {
console.log("在这里可以拿到返回的数据:", data);
});