Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise深入理解 #1

Open
YeaseonZhang opened this issue Dec 12, 2017 · 0 comments
Open

Promise深入理解 #1

YeaseonZhang opened this issue Dec 12, 2017 · 0 comments

Comments

@YeaseonZhang
Copy link
Member

YeaseonZhang commented Dec 12, 2017

Promise深入理解

image

什么是Promise

Promise的核心理念是一个异步操作的结果,Promise包含两部分

  • [[PromiseStates]]
  • [[PromiseValue]]

Promise状态三种可能:

  • pending: 悬而未决
  • resolved: 决定
  • rejected: 拒绝

state

异步性

const p = new Promise((resolve, reject) => {
  resolve('success');
});

p.then((value) => {
  console.log(value);
});

console.log('Called first ?');

Promisethen()具有异步性,当执行到.then()部分,这部分会自动进入到Promise的异步事件队列,不会阻塞同步代码的执行,所以Called first?先输出。

输出结果

Called first ?
success

立即执行性

const p = new Promise((resolve, reject) => {
  console.log('Create a promise');
  resolve('success');
});

p.then((value) => {
  console.log(value);
});

console.log('After new Promise');

Promise异步性,我们可以推断出,After new Promise,会先于then()方法中的输出。同时Promise立即执行性,定义了promise定义的同时就会立即执行,并不依赖于then()的调用。而且与函数明显不同,函数需要主动调用才会执行。

输出结果

Create a promise
After new Promise
success

Promise的状态

const p1 = new Promise((resolve, reject) => {
  resolve(1);
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(2);
  }, 500);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(3);
  }, 500);
});

console.log(p1);
console.log(p2);
console.log(p3);

setTimeout(() => {
  console.log('p2-setTimeout:', p2);
}, 501);

setTimeout(() => {
  console.log('p3-setTimeout:', p3);
}, 501);

p1.then((value) => {
  console.log('p1-then:', value);
});

p2.then((value) => {
  console.log('p2-then:', value);
});

p3.catch((err) => {
  console.log('p3-catch', err);
});

Promise创建完成时,处于 pending 状态;
Promise执行了resolve方法,Promise对象的状态会变成 resolved 状态;
Promise执行了reject方法,Promise对象的状态会变成 rejected 状态;

timeline

先输出

Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

然后输出

p1-then: 1

500ms之后,p2p3Promise状态被执行,then被触发,输出:

p2-then: 2
p3-catch 3

最后会输出:

p2-setTimeout: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
p3-setTimeout: Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}

状态不可逆性

const p1 = new Promise((resolve, reject) => {
  resolve('p1 success 1');
  resolve('p1 success 2');
});

const p2 = new Promise((resolve, reject) => {
  resolve('p2 success');
  reject('p2 reject');
});

p1.then((value) => {
  console.log(value);
});

p2.then((value) => {
  console.log(value);
}, (err) => {
  console.log(err);
});

Promise一旦变成resolved或是rejected,这个状态就不能再次变化,这就是Promise的不可逆性。

输出

p1 success 1
p2 success

链式调用

const p = new Promise(((resolve, reject) => {
  resolve(1);
}));

p.then((value) => {
  console.log(value);
  return value * 2;
}).then((value) => {
  console.log(value);
}).then((value) => {
  console.log(value);
  return Promise.resolve('resolve');
}).then((value) => {
  console.log(value);
  return Promise.reject('reject');
}).then((value) => {
  console.log('resolve: ', value);
}, (err) => {
  console.log('reject: ', err);
});

Jquery对象链式调用是执行jquery方法之后,会继续返回jquery对象;类似这个原理,Promise对象的then方法会返回一个新的Promise对象,这样就可以继续调用then方法。同样then方法中的两个参数还是fulfilled对象和rejected对象。

chain

return一个值或者Promise.resolve()时,状态为 resolved
throw一个异常或者return Promise.reject(),状态为 rejected

: 当then()方法中没有return时,会默认返回undefined,状态为 resolved

输出

1
2
undefined
resolve
reject: reject

Promise中的异常处理

const p1 = new Promise((resolve, reject) => {
  foo.bar();
  resolve(1);
});

p1.then((value) => {
  console.log('p1 then value: ', value);
}, (err) => {
  console.log('p1 then err: ', err);
}).then((value) => {
  console.log('p1 then then value: ', value);
}, (err) => {
  console.log('p1 then then err: ', err);
});

var p2 = new Promise((resolve, reject) => {
  resolve(2);
});

p2.then((value) => {
  console.log('p2 then value: ', value);
  foo.bar();
}, (err) => {
  console.log('p2 then err: ', err);
}).then((value) => {
  console.log('p2 then then value: ', value);
}, (err) => {
  console.log('p2 then then err: ', err);
  return 1;
}).then((value) => {
  console.log('p2 then then then value: ', value);
}, (err) => {
  console.log('p2 then then then err: ', err);
});

Promise中的异常会交给then方法中的第二个回调函数处理,一旦处理完成,会继续返回一个Promise对象给后续then方法。

可以看到输出是p1p2交替输出的,这个并不一定是交替输出,取决于执行情况,也可能是p2先输出。

输出

p1 then err:  ReferenceError: foo is not defined
p2 then value:  2
p1 then then value:  undefined
p2 then then err:  ReferenceError: foo is not defined
p2 then then then value:  1

Promise.resolve()

Promise.resolve()语法:

Promise.resolve(value);
  • value: 用来解析待返回promise对象的参数,既可以是一个promise对象,也可以是一个thenable(即带有then方法)。
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(p1);
const p3 = new Promise((resolve, reject) => {
  resolve(1);
});

const p4 = new Promise((resolve, reject) => {
  resolve(p1);
});

// console.log(p1);
// console.log(p2);
// console.log(p3);
// console.log(p4);

console.log(p1 === p2);
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);

p4.then((value) => {
  console.log('p4 = ', value);
});

p2.then((value) => {
  console.log('p2 = ', value);
});

p1.then((value) => {
  console.log('p1 = ', value);
})

p1: 接收了一个普通值1,所以会返回一个resolved状态的Promise对象,并且值为1
p2: 接收了一个promise对象p1,会直接返回这个promise对象。
p3p4: 通过new方式创建了一个新的promise对象。

所以,p1 === p2,p3p4都是创建的新对象,所以自身和其他三个对象都不相等。

输出

true
false
false
false

但是后三个输出是:

p2 = 1
p1 = 1
p4 = 1

很有意思的是,明明是p4先执行的then方法,但是却是后输出的。

在定义完4个promise对象时,状态分别为:

Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

很明显,p4pending状态,与其他三个不同,因为p4resolve中接收的参数是一个promise对象p1resolve会对p1进行“拆箱”操作,这个过程是异步的。

:把基本数据类型转换为对应的引用类型的操作称为装箱,把引用类型转换为基本的数据类型称为拆箱。

resolve() & reject() 的区别

const p1 = new Promise((resolve, reject) => {
  resolve(Promise.resolve('resolve'));
});

const p2 = new Promise((resolve, reject) => {
  resolve(Promise.reject('reject'));
});

const p3 = new Promise((resolve, reject) => {
  reject(Promise.resolve('resolve'));
});

p1.then((value) => {
  console.log('p1-resolve:', value);
}, (err) => {
  console.log('p1-reject:', err);
});

p2.then((value) => {
  console.log('p2-resolve:', value);
}, (err) => {
  console.log('p2-reject:', err);
});

p3.then((value) => {
  console.log('p3-resolve:', value);
}, (err) => {
  console.log('p3-reject:', err);
});

resolve方法和reject方法除了在状态上有区别,处理方式上也有区别,resolve方法上面提到了会对promise对象“拆箱”,但是reject方法不会。

p3没有“拆箱”操作,所以会最先输出,直接调用reject方法,输出Promise.resolve('resolve')对象
p1会“拆箱”得到Promise.resolve('resolve')这个promise对象的状态和值,调用resolve方法。
p2会“拆箱”得到Promise.reject('reject')这个promise对象的状态和值,因为得到的状态是rejected,所以会调用reject方法。

输出

p3-reject: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "resolve"}
p1-resolve: resolve
p2-reject: reject

all() & race() & then() 区别

Promise.all()语法:

Promise.all(iterable);

Promise.race()语法:

Promise.race(iterable)
  • iterable: 可迭代对象,例如一个数组。
let timerPromisefy = (delay) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(delay);
    }, delay);
  });
}

console.time('Promise all');
Promise.all([
  timerPromisefy(1),
  timerPromisefy(7),
  timerPromisefy(10),
  timerPromisefy(9)
]).then((value) => {
  console.timeEnd('Promise all');
});

console.time('Promise then');
timerPromisefy(1).then(() => {
  return timerPromisefy(7)
}).then(() => {
  return timerPromisefy(10)
}).then(() => {
  return timerPromisefy(9)
}).then(() => {
  console.timeEnd('Promise then')
});

console.time('Promise race');
Promise.race([
  timerPromisefy(1),
  timerPromisefy(7),
  timerPromisefy(10),
  timerPromisefy(9)
]).then(value => {
  console.timeEnd('Promise race');
});

Promise.all()方法返回一个Promise,当iterable参数中的 promise 并行执行,当所有 promise 都已经 resolve 了,返回 resolved 状态。当传递的 promise 包含一个 reject ,则返回 rejected 状态。
如果Promise.all()返回 resolved , 那么执行时间取决于执行最最慢的那个 promise;如果Promise.all()返回 rejected , 执行时间取决于第一个返回 rejected 的执行时间。

Promise.race()方法返回一个Promise,当iterable参数中只要有一个 promise 状态被判定了,那么就返回该状态。
所以Promise.race()的执行时间取决于执行最快的那个 promise

Promise.then()方法的执行时间,是每个链式调用总时间之和。

输出

Promise race: 2.3232421875ms
Promise all: 3.675048828125ms
Promise then: 31.32373046875ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant