function a() {
console.log("a");
setTimeout(() => {
console.log("a1");
}, 1000);
}
function b() {
console.log("b");
}
a();
b();
//打印结果 a,b,a1
//这里b不用等待一秒后a1打印完再打印,这里可以结合js的事件循环机制一起看,更加细节
// 附上js的事件循环机制文章:https://segmentfault.com/a/1190000039866826
function b(value) {
var bb = "everyone";
console.log(value + bb);
}
function a(callback) {
let value = "hello ";
setTimeout(() => {
callback(value);
}, 1000);
}
a(b);
//这是一个异步回调,1秒钟之后才会执行b函数
let a = setTimeout(function a() {
var name1 = "hello ";
try {
setTimeout(function b() {
var name2 = "everyone " + name1; //如果这里的b函数,name2改动了,下面的c函数打印的值就会受影响,牵一发而动全身
setTimeout(function c() {
var name3 = "yeah!";
return name3; // 在这里return只是为了演示,return name3 不能被接收到
console.log(name2 + name3);
}, 1000);
}, 1000);
} catch (e) {
console.log(e, "不能捕获错误"); //这个try,catch只是为了演示,这里不能捕获到错误,因为try catch不能捕获异步错误,当执行到try时,try里面的代码放到到异步的任务队列里,没有try到任何内容,所以catch里面不打印。让同步代码执行完,去执行异步的任务队列时,这时候会报错。
}
}, 1000);
console.log(a); //这里a不是name3,所以不能直接return
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功");
// reject("失败");
}, 1000);
}).then(
(value) => {
console.log(value, "这是成功返回的值");
},
(reason) => {
console.log(reason, "这是失败的原因");
}
);
由于resolve和reject可执行,所以都是函数
class Promise {//类
constructor(executor) { // 构造函数
// 成功
let resolve = () => { };
// 失败
let reject = () => { };
//执行executor可能会报错,把错误捕获,传递到reject里面去
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
}
Promise有三种状态,分别为成功Fulfilled,失败Rejected,等待Pending。
resolve和reject就是用来更改状态的
const PENDING = "pending"; //等待
const FULFILLED = "fulfilled"; // 成功
const REJECTED = "rejected"; // 失败
class Promise {
constructor(exector) {
const resolve = (value) => {
// 一但状态确定就不可更改
if (this.status !== PENDING) return;
//更改状态,状态变成成功
this.status = FUlFILLED;
//把成功的值保持下来
this.value = value;
};
const reject = (reason) => {
if (this.status !== PENDING) return;
this.status = REJECTED;
this.reason = reason;
};
try {
exector(resolve, reject); //立即执行,resolve
} catch (e) {
reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallBack = undefined;
rejectedCallBack = undefined;
}
class Promise{
constructor(executor){...}
status = PENDING;
value = undefined;
reason = undefined;
// then 方法 有两个参数onFulfilled onRejected
then(successCallback, failCallback) {
// 状态为fulfilled,successCallback,传入成功的值
if (this.status === FULFILLED) {
//用try,catch捕获在then方法里面抛出的错误,传入reject中
try {
successCallback(this.value);
} catch (error) {
reject(error);
}
}
// 状态为rejected,执行failCallback,传入失败的原因
if (this.status === REJECTED) {
try {
failCallback(this.reason);
} catch (error) {
this.reject(error);
}
}
}
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(exector) {
const resolve = (value) => {
// 一但状态确定就不可更改
if (this.status !== PENDING) return;
//更改状态,状态变成成功
this.status = FUlFILLED;
//把成功的值保持下来
this.value = value;
// if (this.fulfilledCallBack) this.fulfilledCallBack(value);
if (this.fulfilledCallBack) {
this.fulfilledCallBack.map((item) => {
item(value);
return;
});
}
};
const reject = (reason) => {
if (this.status !== PENDING) return;
this.status = REJECTED;
this.reason = reason;
// if (this.rejectedCallBack) this.rejectedCallBack(reason);
if (this.rejectedCallBack) {
this.rejectedCallBack.map((item) => {
item(reason);
return;
});
}
};
try {
exector(resolve, reject);
} catch (e) {
reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallBack = [];
rejectedCallBack = [];
then(successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.value);
} else if (this.status === REJECTED) {
failCallback(this.reason);
} else {
// this.fulfilledCallBack=successCallback;
// this.rejectedCallBack=failCallback;
// 这里是pending的状态
this.fulfilledCallBack.push(successCallback);
// 用数组把多个成功或者失败回调存储起来,等到resolve或者reject的时候,依次执行
this.rejectedCallBack.push(failCallback);
}
}
}
then方法的参数是可选的
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor){...}
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallBack = [];
rejectedCallBack = [];
then(successCallback, failCallback) {
// 这里是如果then没有传参数,对应的
// then() 相当于----> then(value=>value,(reason)=>{throw reason})
const successCallback = successCallback?successCallback:(value)=>value
const failCallback = failCallback?failCallback:(error)=>{throw error}
if (this.status === FULFILLED) {
successCallback(this.value);
} else if (this.status === REJECTED) {
failCallback(this.reason);
} else {
this.fulfilledCallBack.push(successCallback);
this.rejectedCallBack.push(failCallback);
}
}
then方法的链式调用
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor){...}
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallBack = [];
rejectedCallBack = [];
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : (value) => value;
failCallback = failCallback
? failCallback
: (reason) => {
throw reason;
};
let p = new MyPromise((resolve, reject) => {
//then是链式调用的,1.所以返回promsie对象
// 2.把上一个then返回的值传递下去(resolve(value)或者reject(reason)),如果是promise,判断paromsie的状态,成功还是失败,调用resolve或者reject把状态告知下一个then方法
if (this.status === FULFILLED) {
setTimeout(() => {
// 这里的定时器是为了得到p, 因为这里p要在new promise()执行完才得到,现在在执行过程中,没法得到,要使用定时器,变成异步,得到 p
try {
// 这里用try catch 是把then()里面的错误捕获,传给reject
const x = successCallback(this.value);
getValueType(p, x, resolve, reject);
} catch (e) {
reject(e);
}
});
} else if (this.status === REJECTED) {
// 类似成功时候的回调
setTimeout(() => {
try {
const x = failCallback(this.reason);
getValueType(p, x, resolve, reject);
} catch (e) {
reject(e);
}
});
} else {
try {
this.fulfilledCallBack.push((value) =>
setTimeout(() =>
getValueType(p, successCallback(value), resolve, reject)
)
);
this.rejectedCallBack.push((reason) =>
setTimeout(() =>
getValueType(p, failCallback(reason), resolve, reject)
)
);
} catch (e) {
reject(e);
}
}
});
return p;
}
}
// 单独抽出一个方法,判断then返回;
// 返回的如果是普通值,直接resolve(value);
// 如果返回的是promise对象,先执行then方法,判断状态,在成功的回调里resolve(value),失败的回调里reject(reason);
const getValueType = (p, x, resolve, reject) => {
// 判断x 和p 是否相等,相等就是自己调用自己,报“循环引用”错误
if (p === x) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
// 用instanceof判断x是不是MyPromise的实例对象
if (x instanceof MyPromise) {
return x.then(resolve, reject); //简写
} else {
return resolve(x);
}
};
catch捕获错误
class MyPromise {
constructor(executor){...}
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallBack = [];
rejectedCallBack = [];
then(){...}
catch(failCallBack) {
// 相当于then()第一个参数是undefined
return this.then(undefined, failCallBack);
}
}
const getValueType =()=>{...}
Promise.all(),Promise.race方法
class MyPromise {
constructor(executor){...}
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallBack = [];
rejectedCallBack = [];
then(){...}
catch() {...}
static all(array) {
let result = [];
let key = 0;
return new MyPromise((resolve, reject) => {
function addData(i, value) {
result[i] = value;
key++;
// 判断key === array.length,这时候,所以的异步promise才执行完毕
if (key === array.length) {
// 之所以不在for下面执行resolve,在这里执行,因为如果数组里面是异步的promise对象的话,要等它执行完在返回再resolv出去
resolve(result);
}
}
for (let i = 0; i < array.length; i++) {
if (array[i] instanceof MyPromise) {
//是promise对象就把成功的值push进数组,失败的值reject出去
array[i].then(
(value) => addData(i, value),
(reason) => reject(reason)
);
} else {
addData(i, array[i]); //是普通值就push进数组
}
}
// resolve(result); // 如果在这里执行resolve的话,不会等promise对象执行完毕
});
}
static race(array) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < array.length; i++) {
if (array[i] instanceof MyPromise) {
// 成功返回第一个resolve,失败返回第一个reject
array[i].then(resolve, reject);
} else {
// 会返回第一个resolve,因为状态已经改变了,后面resolve不会再执行
resolve(array[i]);
}
}
});
}
}
const getValueType =()=>{...}
Promise.resolve(),Promise.reject()方法
class MyPromise {
constructor(executor){...}
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallBack = [];
rejectedCallBack = [];
then(){...}
catch(){...}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise((resolve, reject) => {
resolve(value);
});
}
static reject(value) {
if (value instanceof MyPromise) return value;
return new MyPromise((resolve, reject) => {
reject(value);
});
}
}
const getValueType =()=>{...}
finally无论失败还是成功都会执行
class MyPromise {
constructor(executor){...}
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallBack = [];
rejectedCallBack = [];
then(){...}
catch(){...}
static resolve(value){...}
finally(callBack) {
// 1.首先要知道状态,那调用then()就能知道状态
return this.then(
// 2.return出去,是因为要返回一个promsie去链式调用
(value) => {
// callBack();
// return value; // 3.还有把值return出去,便于下一个then()接收
return MyPromise.resolve(callBack()).then(() => value); // 这里是finally的回调函数可能返回一个promsie对象,那就要等这个promsie对象执行完毕,再执行后面的then方法,于是,不管是返回普通值还是promsie对象,直接调用resolve()转成promise对象
},
(reason) => {
// callBack();
// throw reason;
return MyPromise.resolve(callBack()).then(() => {
throw reason;
});
}
);
}
}
const getValueType =()=>{...}
function* fun1() {
console.log("start");
try{
// 在函数内部,可以随时通过yield向外返回一个值
// yield关键词不会向return一样结束这个生成器函数的执行,只是暂停这个生成器函数的执行。直到外界再去执行yield方法时,从yield这个位置继续往下执行
let aa = yield "foo";
// 这里"bar",会作为yield "foo"的返回值,即 aa = "foo"
}catch(error){
console.log(error,"error")
}
}
const generator = fun1();
// 调用fun1函数不会并不会立即去执行这个函数,而是得到一个生成器对象
console.log(generator,"generator")
const result = generator.next();
// 直到我们手动调用这个对象的next方法,这个函数的函数体才会开始执行
// 在next方法返回的对象{value: "foo", done: false},去拿到yeild返回的值
// next方法返回的对象里面的done属性表示这个生成器是否已经全部执行完了
console.log(result,"result")
// 调用next传入了参数的话,传入的参数会作为yield语句的返回值
generator.next("bar")
// throw方法也是让函数继续向下执行,只不过生成器函数内部抛出一个异常,要用try,catch去捕获
generator.throw("报错啦")
//ajax("http://www.baidu.com")函数这里是一个伪代码,假设返回一个promise对象
function ajax(){
return new Promise(...)
}
function* main(){
const data1 = yeild ajax("http://www.baidu1.com")
console.log(data1)
const data2 = yeild ajax("http://www.baidu2.com")
console.log(data2)
}
const g = main()
const result = g.next() //这里result就是一个生成器对象,value值是yeild ajax("http://www.baidu.com")返回的promise对象
result.value.then((value)=>{
const result1 = g.next(value) // 把promise执行完返回的值,传给data1
if(result1.done) return
result1.value.then((value)=>{
let result2 = g.next(value) // 把promise执行完返回的值,传给data2
if(result3.done) return
// ...如此往复,可以使用递归的方式
})
})
function co(generator){
const g = generator()
function handleResult(result){
if(result.done) return
result.value.then((data)=>{
handleResult(g.next(data))
},(error)=>{
g.throw(error) // 外部用try catch去捕获
})
}
handleResult(g.next())
}
// 调用 co(main)
await只能在async函数里面使用
function* fun() {
let a = yield setTimeout(() => console.log("111", 0));
let b = yield setTimeout(() => console.log("222", 0));
}
/**
* 等价于
*/
async function fun() {
let a = await setTimeout(() => console.log("111", 0));
let b = await setTimeout(() => console.log("222", 0));
}
data URI scheme 允许我们使用内联(inline-code)的方式在网页中包含数据,可以...
简介: 企业上云多账号架构中,如何做到从上到下管理的同时,处理好员工的权限边...
注释1:上图整个大背景是这个网页的全部尺寸,中间的小框才是浏览器中的可见尺寸...
先点赞再看,养成好习惯 前言 这两天在另一个社区看到了一个关于 Tomcat 的提问...
Redis 官方在 2020 年 5 月正式推出 6.0 版本,提供很多振奋人心的新特性,所以...
解决方法如下: 第一种 使用iframe,但是目前使用iframe的人已经越来越少了,而...
content属性一般用于::before、::after伪元素中,用于呈现伪元素的内容。平时con...
John Au-Yeung 来源:medium 译者:前端小智 有梦想,有干货,微信搜索 【大迁世...
1.HTML5的内容类型 内容类型 描述 内嵌 向文档中添加其他类型的内容,例如audio...
复制代码 代码如下: !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional...