全面解析Promise


2020-02-16 JavaScript ES6

ruanyif ES6 入门 + 掘金文章 总结

参考文章:
Promise 对象 - ECMAScript 6 入门
八段代码彻底掌握 Promise

# 三种状态

  • 等待中 pending
  • 完成 fulfilled
  • 拒绝 rejected

立即执行性: 创建 Promise 实例时 作为参数传入的函数会被 立即执行

var p1 = new Promise(function(resolve, reject) {
  // 同步代码 -> 实例创建完成时状态已变为resolved
  resolve(1);
});
var p2 = new Promise(function(resolve, reject) {
  // 异步代码
  setTimeout(function() {
    resolve(2); // 500ms后才执行此步
  }, 500);
});
var p3 = new Promise(function(resolve, reject) {
  // 异步代码
  setTimeout(function() {
    reject(3); // 500ms后才执行此步
  }, 500);
});

// 顺序执行部分
console.log(p1); // resolved状态
// Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
console.log(p2); // pending状态
console.log(p3); // pending状态
// Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
// Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

setTimeout(function() {
  console.log(p2);
}, 1000);
// Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
setTimeout(function() {
  console.log(p3);
}, 1000);
// Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}

// 注册回调函数
p1.then(function(value) {
  console.log(value);
});
p2.then(function(value) {
  console.log(value);
});
p3.catch(function(err) {
  console.log(err);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 工作原理

  1. 生成实例
  2. 指定回调
// 创建一个promise实例 构造函数接收一个函数作为参数
var p1 = new Promise(Fn);
// 该函数 有两个函数作为参数
function Fn(resolve, reject) {
  // 函数内部会定义什么时候让状态变成resolve或reject
  if (异步操作成功) {
    resolve(value);
  } else {
    reject(value);
  }
}
// 以上便是实例生成
// 至此还未告知成功后做什么
// 实例生成后用then方法指定resolved状态和rejeceted状态的回调函数
p1.then(
  val => {
    // 成功后做什么
  },
  err => {
    // 失败后做什么
  }
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

如果后续任务是异步任务,必须 return 一个新的 promise 对象

var p = new Promise(function(resolve, reject) {
  resolve(1);
});
p.then(function(value) {
  //第一个then
  //value = 1
  console.log(value);
  return value * 2;
})
  .then(function(value) {
    //第二个then
    //value = 1 * 2
    console.log(value);
  })
  .then(function(value) {
    //第三个then
    // 无value值
    console.log(value);
    return Promise.resolve("resolve");
  })
  .then(function(value) {
    //第四个then
    //value = 'resolve'
    console.log(value);
    return Promise.reject("reject");
  })
  .then(
    //第五个then
    function(value) {
      console.log("resolve: " + value);
    },
    // 只执行reject err='reject'
    function(err) {
      console.log("reject: " + err);
    }
  );

// 1
// 2
// undefined
// "resolve"
// "reject: reject"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# API

# .then()

  • 回调异步性:
    Promise 接收的函数参数是同步执行的,但 then 方法中的回调函数执行则是异步的,因此,"success"会在后面输出。
var p = new Promise(function(resolve, reject) {
  resolve("success");
});

p.then(function(value) {
  console.log(value);
});

console.log("which one is called first ?");

// "which one is called first ?"
// "success"
1
2
3
4
5
6
7
8
9
10
11
12

# .resolve()

var p1 = Promise.resolve(1);
var p2 = Promise.resolve(p1);
var p3 = new Promise(function(resolve, reject) {
  resolve(1);
});
var p4 = new Promise(function(resolve, reject) {
  resolve(p1);
});

console.log(p1 === p2); // true
console.log(p1 === p3); // false
// 通过new方法创建的是一个新的对象
console.log(p1 === p4); // false
console.log(p3 === p4); // false

p4.then(function(value) {
  console.log("p4=" + value);
});

p2.then(function(value) {
  console.log("p2=" + value);
});

p1.then(function(value) {
  console.log("p1=" + value);
});

// p2=1
// p1=1
// p4=1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

为什么 p4 最后输出?当 resolve 接收参数是 promise 对象时需要进行拆箱

# .resolvevs.reject

var p1 = new Promise(function(resolve, reject) {
  resolve(Promise.resolve("resolve"));
});

var p2 = new Promise(function(resolve, reject) {
  resolve(Promise.reject("reject"));
});

var p3 = new Promise(function(resolve, reject) {
  reject(Promise.resolve("resolve"));
});

p1.then(
  function fulfilled(value) {
    console.log("fulfilled: " + value);
  },
  function rejected(err) {
    console.log("rejected: " + err);
  }
);

p2.then(
  function fulfilled(value) {
    console.log("fulfilled: " + value);
  },
  function rejected(err) {
    console.log("rejected: " + err);
  }
);

p3.then(
  function fulfilled(value) {
    console.log("fulfilled: " + value);
  },
  function rejected(err) {
    console.log("rejected: " + err);
  }
);

// p3 rejected: [object Promise]
// p1 fulfilled: resolve
// p2 rejected: reject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  • 先输出 p3:then 中的 reject 不具备拆箱功能 无需等待即输出[object Promise]
  • p1,p2 中 resolve 正常进行异步的拆箱 然后执行 console.log