Appearance
从零开始,手写完整的Promise原理
上课时间是 周三、周五晚8-10 周日全天. 今日上课时间:早9.30 - 12.00 下午 2.00 - 5.00
实现Promise:https://promisesaplus.com/
课程规划
- 掌握高阶函数的使用,使用高阶函数解决异步问题。 
- 掌握发布订阅模式和观察者模式 
- 掌握promise核心应用,使用promise解决异步编程问题 
- 实现一个完整的promise库 
- 掌握promise中常见的面试题 
- 扩展promise中常见方法 all,race,finally... 
- generator + co 
关于函数
什么是高阶函数: 把函数作为参数或者返回值的一类函数。
before函数
Function.prototype.before = function(beforeFn){
    return ()=>{
        beforeFn();
        this();
    }
}
function fn(){
    console.log('source')
}
const newFn = fn.before(say=>{
    console.log('say');
});
newFn();
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,其实就是给原函数增加一层,不用管原函数内部实现
 *                       wrappers (injected at creation time)
 *                                      +        +
 *                                      |        |
 *                    +-----------------|--------|--------------+
 *                    |                 v        |              |
 *                    |      +---------------+   |              |
 *                    |   +--|    wrapper1   |---|----+         |
 *                    |   |  +---------------+   v    |         |
 *                    |   |          +-------------+  |         |
 *                    |   |     +----|   wrapper2  |--------+   |
 *                    |   |     |    +-------------+  |     |   |
 *                    |   |     |                     |     |   |
 *                    |   v     v                     v     v   | wrapper
 *                    | +---+ +---+   +---------+   +---+ +---+ | invariants
 * perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained
 * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
 *                    | |   | |   |   |         |   |   | |   | |
 *                    | |   | |   |   |         |   |   | |   | |
 *                    | |   | |   |   |         |   |   | |   | |
 *                    | +---+ +---+   +---------+   +---+ +---+ |
 *                    |  initialize                    close    |
 *                    +-----------------------------------------+
 * 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
类型检测
function checkType(content,Type){
    return Object.prototype.toString.call(content) === `[object ${Type}]`
}
const flag = checkType('hello','String');
// -----------------------------------
function checkType(Type){
    return function(content){
        return Object.prototype.toString.call(content) === `[object ${Type}]`
    }
}
const flag = checkType('hello','String');
const util = {};
const types = ['String','Number','Boolean'];
types.forEach(type=>{
    util['is'+type] = checkType(type);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
函数分步传递参数,将函数拆分成功能更具体化的函数
柯里化函数
const currying = (fn,args = []) => {
    let len = fn.length;
    return (..._)=>{
        let arg = args.concat(_);
        if(arg.length < len){
            return currying(fn,arg);
        }
        return fn(...arg);
    }
};
const add = (a, b, c, d, e) => {
  return a + b + c + d + e;
};
let r = currying(add)(1)(2,3)(4,5);
console.log(r);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
柯里化类型函数
const types = ['String','Number','Boolean'];
let utils = {}
types.forEach(type=>{
    utils[`is${type}`] = currying(isType)(type);
})
1
2
3
4
5
2
3
4
5
after函数的应用
const after = (times, callback) => () => {
  if (--times === 0) {
    callback();
  }
};
const newFn = after(3, () => {
  console.log("ok");
});
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
发布订阅模式 、 观察者模式
一种一对多的关系,发布者和订阅者是否有关联,观察者模式基于发布订阅模式
promise面试
promise 中的链式调用如何中断?
Promise.finally实现原理?
promise有哪些缺点?
fetch 无法中断,但是可以丢弃本次请求 依然是基于回调的方式,好处可以扁平化处理我们的逻辑,处理错误比较方便
Promise超时中断如何实现
function wrap(p1){
    let abort;
    let p2 = new Promise((resolve,reject)=>{
        abort = function(){
            reject('失败');
        }
    });
    let p =  Promise.race([p1,p2]);
    p.abort = abort;
    return p;
}
let p = wrap(new Promise((resolve,reject)=>{
    setTimeout(() => {
        resolve();  
    }, 3000);
}))
p.then(()=>{},()=>{console.log('失败')})
p.abort();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
常见代码输出题
// 1
let p = new Promise((resolve,reject)=>{
    reject();
    resolve();
});
p.then(()=>console.log('成功'),()=>console.log('失败'));
1
2
3
4
5
6
2
3
4
5
6
const promise = new Promise((resolve,reject)=>{
    console.log(1);
    resolve();
    console.log(2);
})
promise.then(()=>{
    console.log(3);
})
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Promise.resolve(1)
.then(res=>2)
.catch(err=>3)
.then(res=>console.log(res));
1
2
3
4
2
3
4
Promise.resolve(1)
.then(x=>x+1)
.then(x=>{throw new Error('My Error')})
.catch(()=>1)
.then(x=>x+1)
.then(x=>console.log(x))
.catch(console.error)
1
2
3
4
5
6
7
2
3
4
5
6
7