知识盲区(一)

工作闲暇的期间,会读一些博文,更多的是刷面筋,虽然已经工作稳定。但还是偶尔需要有危机感,去看看现在企业喜欢问什么问题。其实大部分面筋问题都还不是很会。会把知识盲区记录下来,然后整理成博文

这次差不多有Css超出省略企业SSO的实现原理自写Promis

css超出省略

css单行超出省略

1
2
3
4
5
width: 100px;
overflow: hidden;
white-space: no-wrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;

css多行超出省略

1
2
3
4
5
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical

企业sso(单点登陆的实现)

理解

1
sso单点登录,我理解的就是,在一个专门登陆的系统登录后,此后所有类似的系统都不用再写登陆页登陆。

实现

1
2
3
4
1. 用户进入某应用(未登陆)
2. 跳转到sso登陆页,登陆成功
3. 后台server端会存储一个唯一的session,同时浏览器端会存储一个cookie
4. 每次用户下次在访问这个应用时,请求中会带上这个cookie,服务端会根据这个cookie找到唯一的session,判断是否登陆

场景

  1. 应用sso登陆是在同域,
  • cookie不能跨域
  • 应用与sso后台的session也不能共享
    1
    2
    3
    4
    5
    // sso登陆: sso.xxx.com;
    // 应用: app.xxx.com

    // cookie存储在顶域: xxx.com
    // 多个系统session共享,如common session
  1. 应用sso登陆不是在同一个域.
    1
    2
    3
    4
    5
    6
    1. 用户访问app系统
    2. 跳转到cas server sso登陆页
    3. 登陆成功,session存储在sso的后台中,浏览器中写入sso所在域的cookie
    4. sso登陆系统完成后会生成一个service tickets,相当于一个门票。然后跳转到app页面,同时将这个门票作为参数。
    5. app系统拿到这个门票后,从后台向sso发送请求(不会有跨域问题),判断这个门票是否有效
    6. 通过验证后,就会在app所在域里也写入这个cookie,这样下次打开就不用再登陆。

自写promise

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

// 主体函数
function Promise(executor){
let self = this;
self.status="pending";
self.value = null;
self.reson = null;
self.onResolveCallback = [];
self.onRejectCallback=[];

function resolve(value){
if(self.status === "pending"){
self.status = "resolved";
self.value = value;

self.onResolveCallback.forEach((fn)=>{
fn();
})
}
}

function reject(reason){
if(self.status === "pending"){
self.status = "rejected";
self.season = reason;

self.onRejectCallback.forEach((fn)=>{
fn();
})
}
}

try {
executor(resolve,reject);
}catch(err){
throw(err)
}
}


// 辅助函数
function resolvePromise(promise2, x, resolve, reject){
if(promise2 === x) {
return reject(new TypeError("循环引用"))
}

let called = false;

if(x!==null && (typeof x==="object" || typeof x === "function")){
try{
const then = x.then;
if(typeof then === "function"){
const resolveFunc = (y)=>{
if(called) return;
called = true;
resolvePromise(promise2,y,resolve,reject)
};

const rejectFunc = (error)=>{
if(called) return;
called = true;
reject(error);
}
then.call(x,resolveFunc,rejecFunc)
}else{
// 如果是对象或函数,没有thenable,则直接返回
resolve(x)
}
}catch(err){
if(called) return;
called = truel
reject(error);
}

}else{
// x是普通的值,也直接resolve
}
}
  • 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
    44
    45
    46
    47
    48
    49

    Promise.prototype.then = function(onFuifilled, onRejected){
    onFuifilled = typeof onFuifilled === "function" ? onFuifilled : (value)=>{ return value };
    onReject = typeof onReject === "function" ? onReject : (error)=>{ throw error };

    let self = this;

    let promise2 = new Promise((resolve,reject)=>{
    if(self.status === "pending"){
    self.onResolveCallback.push(()=>{
    setTimeout(()=>{
    try {
    let x = onFuifilled(self.value);
    resolvePromise(promise2, x, resolve, reject);
    }catch(err){
    reject(err)
    }
    },0)
    });

    self.onRejectCallback.push(()=>{
    setTimeout(()=>{
    try {
    let x = onRejected(self.reason);
    resolvePromise(promise2, x, resolve, reject);
    }catch(err){
    reject(err);
    }
    },0)
    })
    }else if(self.status === "resolved"){
    setTimeout(()=>{
    try {
    let x = onFuifilled(self.value);
    resolvePromise(promise2, x, resolve, reject);
    }
    }, 0)
    }else if(self.status === "rejected"){
    setTimeout(()=>{
    try {
    let x = onRejected(self.reason);
    resolvePromise(promise2, x, resolve, reject);
    }
    },0)
    }
    });

    return promise2;
    }
  • catch 方法

    1
    2
    3
    Promise.prototype.catch = (onRejected)=>{
    return this.then(null,onRejected);
    }
  • finanlly 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Promise.prototype.finanlly = function(fn){
    return this.then((data)=>{
    setTimeout(fn, 0);
    return data;
    },(reason)=>{
    setTimeout(fn, 0);
    throw reason
    })
    }
  • done 方法

    1
    2
    3
    4
    5
    Promise.prototype.down = function(){
    this.catch((err)=>{
    throw(err)
    })
    }
  • all 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Promise.prototype.all = function(promiseArray){
    reutrn new Promise((resolve,reject)=>{
    const results = [];
    let count = 0;

    for(let i=0; i<promiseArray.length; i++){
    promiseArray[i].then((data)=>{
    results[i] = data;
    count++;
    if(count === promiseArray.length){
    resolve(results)
    }
    },reject)
    }
    })
    }
  • race方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Promise.race = function(promiseArr) {
    return new Promise((resolve, reject) => {
    for (let i = 0; i < promiseArr.length; i++) {
    promiseArr[i].then((data) => {
    resolve(data);
    }, reject)
    }
    });
    };
  • resolve方法

    1
    2
    3
    4
    5
    Promise.resolve = function(value){
    return new Promise((resolve,reject)=>{
    resolvePromise(promise,value,resolve,reject);
    })
    }
  • reject方法

    1
    2
    3
    4
    5
    Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
    reject(reason)
    })
    }
  • defer方法

    1
    2
    3
    4
    5
    6
    7
    8
    Promise.defer = Promise.deferred = function(){
    let dfd = {};
    dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
    });
    return dfd;
    }
-------------本文结束感谢您的阅读-------------