六月第三周(6.22-6.27)的安排

  • promise用法1
  • promise用法2
  • promise手写

用法

promise状态不可逆性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var p1 = new Promise(function(resolve, reject){
resolve("success1");
resolve("success2");
});

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

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

p2.then(function(value){
console.log(value);
});
// 输出
success1
success

promise中的异常处理

  • first scene
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    var p1 = new Promise( function(resolve,reject){
    foo.bar();
    resolve( 1 );
    });

    p1.then(
    function(value){
    console.log('p1 then value: ' + value);
    },
    function(err){
    console.log('p1 then err: ' + err);
    }
    ).then(
    function(value){
    console.log('p1 then then value: '+value);
    },
    function(err){
    console.log('p1 then then err: ' + err);
    }
    );
    // 控制台输出
    p1 then err: ReferenceError foo is not defined
    p1 then then err: undefined
  • second scene
    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
    var p2 = new Promise(function(resolve,reject){
    resolve( 2 );
    });

    p2.then(
    function(value){
    console.log('p2 then value: ' + value);
    foo.bar();
    },
    function(err){
    console.log('p2 then err: ' + err);
    }
    ).then(
    function(value){
    console.log('p2 then then value: ' + value);
    },
    function(err){
    console.log('p2 then then err: ' + err);
    return Promise.resolve('resolve');
    }
    ).then(
    function(value){
    console.log('p2 then then then value: ' + value);
    },
    function(err){
    console.log('p2 then then then err: ' + err);
    }
    );
    // 输出
    p2 then value: 2
    p2 then then err: ReferenceError foo is not defined
    p2 then then then value: resolve
    知识点
  • Promise对象的then方法返回一个新的Promise对象,因此可以通过链式调用then方法。
  • then方法接受两个参数,第一个是promise成功的回调,一个是失败的回调,两个函数只能一个被调用

promise.resolve()

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
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);
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);

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

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

p1.then(function(value){
console.log('p1=' + value);
})
// 控制台输出
true
false
false
false
p2=1
p1=1
p4=1

Promise.resolve()阔以接受一个普通值或者一个Promise对象作为参数
当参数是普通值的时候,返回一个resolved状态的promise对象
当参数是Promise对象时,直接返回这个promise对象,所以p1 === p2

链式调用

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
var p = new Promise(function(resolve, reject){
resolve(1);
});
p.then(function(value){ //第一个then
console.log(value);
return value*2;
}).then(function(value){ //第二个then
console.log(value);
}).then(function(value){ //第三个then
console.log(value);
return Promise.resolve('resolve');
}).then(function(value){ //第四个then
console.log(value);
return Promise.reject('reject');
}).then(function(value){ //第五个then
console.log('resolve: '+ value);
}, function(err){
console.log('reject: ' + err);
})
// 输出
1
2
undefined
resolve
reject: reject

then两个参数的返回值是以下三种情况的一种

  • return 一个同步值或者undefined(没有返回一个值时默认是undefined),then 方法会返回一个resolved状态的promise对象,Promise对象的值就是这个返回值
  • return 另一个Promise,then会根据这个Promise的状态和值创建一个新的Promise对象返回
  • throw 一个同步异常 then方法返回一个rejected状态的promise,值是该异常

resolve vs 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
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);
}
);
// 控制台输出
rejected: [object Promise]
fulfilled: resolve
rejected: resolve
  • Promise回调函数中的第一个参数resolve,会对Promise执行”拆箱”动作。即当resolve的参数是一个Promise对象时,resolve会”拆箱”获取这个Promise对象的状态和值,但这个过程是异步的。p1”拆箱”后,获取到Promise对象的状态是resolved,因此fulfilled回调被执行;
  • p2”拆箱”后,获取到Promise对象的状态是rejected,因此rejected回调被执行。
  • 但Promise回调函数中的第二个参数reject不具备”拆箱“的能力,reject的参数会直接传递给then方法中的rejected回调。因此,即使p3 reject接收了一个resolved状态的Promise,then方法中被调用的依然是rejected,并且参数就是reject接收到的Promise对象。

拆箱是异步操作,所以不具备拆箱的3执行的是同步操作

扩展—— try catch

问: 用一句话描述js异常是否能被try catch到
答: 能捕捉到的异常必须是线程执行已经进入try catch但try catch未执行完成的时候抛出来的

红绿灯问题

Qs: 题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯2秒亮一次;如何让三个灯不断交替重复亮灯?(用 Promise 实现)

1
2
3
4
5
6
7
8
9
function red(){
console.log('red');
}
function green(){
console.log('green');
}
function yellow(){
console.log('yellow');
}

利用then和递归实现

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
function red(){
console.log('red');
}
function green(){
console.log('green');
}
function yellow(){
console.log('yellow');
}

var light = function(timmer, cb){
return new Promise(function(resolve, reject) {
setTimeout(function() {
cb();
resolve();
}, timmer);
});
};

var step = function() {
Promise.resolve().then(function(){
return light(3000, red);
}).then(function(){
return light(2000, green);
}).then(function(){
return light(1000, yellow);
}).then(function(){
step();
});
// 或者换种写法
var p4 = new Promise(function(resolve, reject) {
resolve('i am cpp')
})
p4.then(function(val){
console.log(val) // i am cpp
return light(3000, red);
}).then(function(){
return light(2000, green);
}).then(function(){
return light(1000, yellow);
})
}
step();

参考链接