Promise
原理
// promise 承诺
// 1. 实现承诺 resolve (解决问题)
// 2. 石沉大海 reject (拒绝接收)
// 3. 等待... pending (苦苦等待...)
// promise:解决异步(互不相干你做你的我做我的互不阻塞互不等待)流程化的一种手段
// 同步:A任务结束出结果,B任务拿到A任务的结果才执行下面的任务
// Promise 构造函数 需要new
// Promise 参数(有且仅有一个) excutor 执行器
// excutor => resolve reject 函数
// excutor 在 new Promise 时抵用
// excutor 是同步执行的
let promise = new Promise((resolve, reject) => {
// console.log(1);
// resolve('承诺实现');
reject('承诺石沉大海');
// throw new Error('Error: 承诺石沉大海');// 手动抛出错误 和reject一样的
});
// console.log(2); // 先打印1 在打印2
// 说明then是异步调用
// promise.then((res) => {
// console.log('then');
// console.log(res);
// }, (err) => {
// console.log(err);
// })
promise.then((res) => {
console.log('then');
console.log(res);
}).catch(err => {
console.log(err);
})
console.log('Global'); // 先打印Global 在打印then
// err在第一个then没有处理,具有穿透性,下个then处理也是有结果的,
// 没有处理err的话,有catch就走catch
promise.then((res) => {
console.log('then');
}).then(() => {
}).then(()=>{
}, (err) => {
console.log(err)
})
// promise.then((res) => {
// console.log('aa');
// return new Promise((resolve, reject) => resolve('成功'))
// }).then((res) => {
// console.log(res);
// })
了解一下回调地狱
// 高阶函数:函数参数里面有函数,闭包返回一个函数
// function doSth (t, cb) {
// return function () {
// if (--t === 0) {
// cb();
// }
// }
// }
function logSth (cb) {
console.log('aaaaaaaaaa');
cb();
}
function logSth2 (cb) {
console.log('bbbbbbbbb');
cb();
}
function logSth3 () {
console.log('cccccccccc');
}
// let fn = doSth(4, logSth.bind(null, logSth2));
// 回调地狱
function doSth (t) {
return function () {
if ( --t === 0 ) {
logSth(function () {
logSth2(function () {
logSth3()
})
})
}
}
}
let fn = doSth(4, logSth)
fn();
fn();
fn();
fn(); // aaaaaaaaaaa
结合node.js(fs.readFile)使用promise
const fs = require('fs');
let uid = 3;
fs.readFile('./data/user.json', 'utf8', function (err, data) {
const userData = JSON.parse(data),
userInfo = userData.filter(item => item.id === uid)[0];
fs.readFile('./data/userCourse.json', 'utf8', function (err, data) {
const userCourseData = JSON.parse(data),
userId = userInfo.id,
userCourse = userCourseData.filter(item => {
return item.uid === userId
})[0];
fs.readFile('./data/course.json', 'utf8', function (err, data) {
const courseData = JSON.parse(data),
userCourses = userCourse.courses;
let _arr = [];
userCourses.map(id => {
courseData.map((item) => {
if (item.id) {
_arr.push(item);
}
})
});
const userCourseInfo = {
username: userInfo.username,
cuerses: _arr
}
fs.writeFileSync(`./data/${userInfo.username}.json`, JSON.stringify(userCourseInfo))
});
})
})
const fs = require('fs');
let uid = 1;
function readFile (path, prevData) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', function (err, data) {
if (err) {
reject(err);
}
const resData = JSON.parse(data);
resolve({
prevData,
resData
})
})
})
}
readFile('./data/user.json')
.then((res)=>{
const { resData } = res,
userInfo = resData.filter(item => item.id === uid)[0];
return readFile('./data/userCourse.json', userInfo);
})
.then((res) => {
const { prevData, resData } = res,
userId = prevData.id,
userCourse = resData.filter(item => item.uid === userId)[0];
return readFile('./data/course.json',{
username: prevData.username,
userCourse
})
})
.then((res) => {
const { prevData, resData } = res,
userCourses = prevData.userCourse.courses;
let _arr = [];
userCourses.map(id => {
resData.map(item => {
if (item.id === id) {
_arr.push(item);
}
})
});
const userCourseInfo = {
username: prevData.username,
courses: _arr
}
fs.writeFileSync(`./data/${userCourseInfo.username}.json`, JSON.stringify(userCourseInfo));
})
.catch((err) => {
console.log(err);
})
promise解决异步并发的问题
Promise.all()
const fs = require('fs');
var num= 1;
function readFile(path, isSetError) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', function (err, data) {
if (err || isSetError) {
reject('承诺石沉大海了~~~~~'+ num ++);
}
const resData = JSON.parse(data);
resolve(resData);
})
})
}
readFile('./data/user.json').then((res) => {
console.log(res);
// return Promise.resolve("成功"); //和下面写法是一样的
return Promise.reject("失败"); //和下面写法是一样的
// return new Promise((resolve,reject) => {resolve("成功")});
}).then((res) => {
console.log(res); // 成功
},(err) => { //当为reject时走then(不管有没有catch)
console.log("then" + err); // then失败
}
).catch((err) =>{ //当为reject时then没有err走catch
console.log("catch" + err); // catch失败
})
// readFile('./data/user.json').then((res) => {
// console.log(res);
// })
// readFile('./data/userCourse.json').then((res) => {
// console.log(res);
// })
// readFile('./data/course.json').then((res) => {
// console.log(res);
// })
// 合并三个文件内部的内容为一个数组 并且 按照顺序排列 如果一个读取失败, 就让这个数组返回rejected(失败状态)
// 接收interable(可迭代的对象)类型的数据 => Array Set Map
// Promise.all([
// readFile('./data/user.json'),
// readFile('./data/userCourse.json', true),
// readFile('./data/course.json')
// ]).then((res) => {
// console.log(res);
// }).catch((err) => {
// console.log(err);
// })
// 用多个异步任务并发运行,他的结果创建承诺之后使用,等待所有任务结果的完成
// interable内部元素传递的是promise对象集合,如果不是promise,直接resolve Promise.resolve(0 || '123' || true)
// interable内部没有元素,返回空数组;
// 有一个promise是rejected 实例回调rejected
// 失败原因是第一个失败的promise结果
Promise.race可以测试请求的速度
Promise.race()
const fs = require('fs');
function readFile (path, isSetError) {
return new Promise ((resolve, reject) => {
fs.readFile(path, "utf8", function(err, data) {
if (err || isSetError) {
reject('承诺石沉大海....')
}
const resData = JSON.parse(data);
resolve(resData);
})
})
}
Promise.race([
// readFile('./data/user.json', true),
// readFile('./data/userCourse.json'),
// readFile('./data/course.json')
])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
})
// 谁先完成就返回哪个promise结果,无论是fullfilled(完全完成)还是rejected(失败)
// 如果可迭代容器为空的话,就返回的promise为pending (等待的状态)
// 可以用来资源或者接口的响应速度
function getImg () {
return new Promise((resolve, reject) => {
const oImg = new Image();
oImg.onload = function () {
resolve(oImg);
}
oImg.src = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1604564434152&di=f115b9bbe7f8763e6a3e83a131f46b27&imgtype=0&src=http%3A%2F%2Fgss0.baidu.com%2F-Po3dSag_xI4khGko9WTAnF6hhy%2Fzhidao%2Fpic%2Fitem%2F728da9773912b31b2b0d907a8018367adab4e104.jpg';
})
}
function timeout () {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('图片请求超时');
}, 100)
})
}
Promise.race([
getImg(),
timeout()
])
.then((res) => {
console.log(res);
})
.catch((err) =>{
console.log(err);
})
Promise文档解读
MyPromise.js文件:
const Pending = 'Pending',
FulFilled = 'FulFilled',
Rejected = 'Rejected';
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<MyPromise>'));
}
let called = false;
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
let then = x.then; // throw Error
if (typeof then === 'function') { // 认定为Promise
then.call(x, (y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, (r) => {
if (called) return;
called = true;
reject(r);
})
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
class MyPromise {
constructor(executor) {
this.status = Pending;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === Pending) {
this.status = FulFilled;
this.value = value;
// 发布
this.onFulfilledCallbacks.forEach(fn => fn());
}
}
const reject = (reason) => {
if (this.status === Pending) {
this.status = Rejected;
this.reason = reason;
// 发布
this.onRejectedCallbacks.forEach(fn => fn());
}
}
// 捕获异常
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
// x 可能是普通值 或者 promise
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FulFilled) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0);
} else if (this.status === Rejected) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0);
} else if (this.status === Pending) {
// 订阅的过程
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
console.log(e);
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0);
})
}
});
return promise2;
}
catch (errCallback) {
return this.then(null, errCallback);
}
}
// common.js模块导出
module.exports = MyPromise;
index.js文件
const MyPromise = require('./MyPromise');
let promise1 = new MyPromise((resolve, reject) => {
resolve('promise1');
// reject('Error');
})
let promise2 = promise1.then((value) => {
// return new Error('Error');
// return Promise.resolve('Promise resolve');
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(new MyPromise((resolve, reject) => {
resolve(new MyPromise((resolve, reject) => {
resolve('new Promise resolve')
}));
}));
}, 2000);
});
}, (reason) => {
return reason;
});
promise2.then().then().then().then().then((value) => {
// console.log('fulfilled: ' + value);
throw Error('Error');
}, (reason) => {
console.log('rejected: ' + reason);
})
.catch((e) => {
console.log(e);
})
版权声明:本文为beLaity原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。