記錄--通過手寫,分析axios核心原理

来源:https://www.cnblogs.com/smileZAZ/archive/2022/09/19/16708303.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、axios簡介 axios是什麼? Axios 是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中。 axios有什麼特性?(不得不說面試被問到幾次) 從瀏覽器中創建 XMLHttpRequests 從 ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

一、axios簡介

axios是什麼?

Axios 是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中。

axios有什麼特性?(不得不說面試被問到幾次)

  • 從瀏覽器中創建 XMLHttpRequests
  • 從 node.js 創建 http 請求
  • 支持 Promise API
  • 攔截請求和響應
  • 轉換請求數據和響應數據
  • 取消請求
  • 自動轉換 JSON 數據
  • 客戶端支持防禦 XSRF

實際上,axios可以用在瀏覽器和 node.js 中是因為,它會自動判斷當前環境是什麼,如果是瀏覽器,就會基於XMLHttpRequests實現axios。如果是node.js環境,就會基於node內置核心模塊http實現axios

簡單來說,axios的基本原理就是

  1. axios還是屬於 XMLHttpRequest, 因此需要實現一個ajax。或者基於http
  2. 還需要一個promise對象來對結果進行處理

有什麼不理解的或者是建議歡迎評論提出.項目已經放到 github:github.com/Sunny-lucki…

二、基本使用方式

axios基本使用方式主要有

  1. axios(config)
  2. axios.method(url, data , config)
// index.html文件
<html>
<script type="text/javascript" src="axios"></script>
<body>
<button class="btn">點我發送請求</button>
<script>
    document.querySelector('.btn').onclick = function() {
        // 分別使用以下方法調用,查看myaxios的效果
        axios.post('/postAxios', {
          name: '小美post'
        }).then(res => {
          console.log('postAxios 成功響應', res);
        })

        axios({
          method: 'post',
          url: '/getAxios'
        }).then(res => {
          console.log('getAxios 成功響應', res);
        })
    }
</script>
</body>
</html>
</html>

三、實現axios和axios.method

從axios(config)的使用上可以看出導出的axios是一個方法。從axios.method(url, data , config)的使用可以看出導出的axios上或者原型上掛有get,post等方法

實際上導出的axios就是一個Axios類中的一個方法。

如代碼所以,核心代碼是request。我們把request導出,就可以使用axios(config)這種形式來調用axios了。

class Axios {
    constructor() {

    }

    request(config) {
        return new Promise(resolve => {
            const {url = '', method = 'get', data = {}} = config;
            // 發送ajax請求
            const xhr = new XMLHttpRequest();
            xhr.open(method, url, true);
            xhr.onload = function() {
                console.log(xhr.responseText)
                resolve(xhr.responseText);
            }
            xhr.send(data);
        })
    }
}
怎麼導出呢?十分簡單,new Axios,獲得axios實例,再獲得實例上的request方法就好了。
// 最終導出axios的方法,即實例的request方法
function CreateAxiosFn() {
    let axios = new Axios();
    let req = axios.request.bind(axios);
    return req;
}

// 得到最後的全局變數axios
let axios = CreateAxiosFn();

點擊查看此時的myAxios.js

現在axios實際上就是request方法。

你可能會很疑惑,因為我當初看源碼的時候也很疑惑:幹嘛不直接寫個request方法,然後導出呢?非得這樣繞這麼大的彎子。別急。後面慢慢就會講到。

現在一個簡單的axios就完成了,我們來引入myAxios.js文件並測試一下可以使用不?

簡單的搭建伺服器:

//server.js
var express = require('express');
var app = express();

//設置允許跨域訪問該服務.
app.all('*', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    res.header('Access-Control-Allow-Methods', '*');
    res.header('Content-Type', 'application/json;charset=utf-8');
    next();
});

app.get('/getTest', function(request, response){
    data = {
        'FrontEnd':'前端',
        'Sunny':'陽光'
    };
    response.json(data);
});
var server = app.listen(5000, function(){
    console.log("伺服器啟動");
});

index.html

//index.html
<script type="text/javascript" src="./myAxios.js"></script>

<body>
<button class="btn">點我發送請求</button>
<script>
    document.querySelector('.btn').onclick = function() {
        // 分別使用以下方法調用,查看myaxios的效果
        axios({
          method: 'get',
          url: 'http://localhost:5000/getTest'
        }).then(res => {
          console.log('getAxios 成功響應', res);
        })
    }
</script>
</body>

點擊按鈕,看看是否能成功獲得數據。

可喜可賀,成功。

現在我們來實現下axios.method()的形式。

思路。我們可以再Axios.prototype添加這些方法。而這些方法內部調用request方法即可,如代碼所示:

// 定義get,post...方法,掛在到Axios原型上
const methodsArr = ['get', 'delete', 'head', 'options', 'put', 'patch', 'post'];
methodsArr.forEach(met => {
    Axios.prototype[met] = function() {
        console.log('執行'+met+'方法');
        // 處理單個方法
        if (['get', 'delete', 'head', 'options'].includes(met)) { // 2個參數(url[, config])
            return this.request({
                method: met,
                url: arguments[0],
                ...arguments[1] || {}
            })
        } else { // 3個參數(url[,data[,config]])
            return this.request({
                method: met,
                url: arguments[0],
                data: arguments[1] || {},
                ...arguments[2] || {}
            })
        }

    }
})

我們通過遍歷methodsArr數組,依次在Axios.prototype添加對應的方法,註意的是'get', 'delete', 'head', 'options'這些方法只接受兩個參數。而其他的可接受三個參數,想一下也知道,get不把參數放body的。

但是,你有沒有發現,我們只是在Axios的prototype上添加對應的方法,我們導出去的可是request方法啊,那怎麼辦? 簡單,把Axios.prototype上的方法搬運到request上即可。

我們先來實現一個工具方法,實現將b的方法混入a;

const utils = {
  extend(a,b, context) {
    for(let key in b) {
      if (b.hasOwnProperty(key)) {
        if (typeof b[key] === 'function') {
          a[key] = b[key].bind(context);
        } else {
          a[key] = b[key]
        }
      }
      
    }
  }
}

然後我們就可以利用這個方法將Axios.prototype上的方法搬運到request上啦。

我們修改一下之前的CreateAxiosFn方法即可

function CreateAxiosFn() {
  let axios = new Axios();
  
  let req = axios.request.bind(axios);
  增加代碼
  utils.extend(req, Axios.prototype, axios)
  
  return req;
}

點擊查看此時的myAxios.js

現在來測試一下能不能使用axios.get()這種形式調用axios。

<body>
<button class="btn">點我發送請求</button>
<script>
    document.querySelector('.btn').onclick = function() {

        axios.get('http://localhost:5000/getTest')
            .then(res => {
                 console.log('getAxios 成功響應', res);
            })

    }
</script>
</body>

害,又是意料之中成功。

再完成下一個功能之前,先給上目前myAxios.js的完整代碼

class Axios {
    constructor() {

    }

    request(config) {
        return new Promise(resolve => {
            const {url = '', method = 'get', data = {}} = config;
            // 發送ajax請求
            console.log(config);
            const xhr = new XMLHttpRequest();
            xhr.open(method, url, true);
            xhr.onload = function() {
                console.log(xhr.responseText)
                resolve(xhr.responseText);
            }
            xhr.send(data);
        })
    }
}

// 定義get,post...方法,掛在到Axios原型上
const methodsArr = ['get', 'delete', 'head', 'options', 'put', 'patch', 'post'];
methodsArr.forEach(met => {
    Axios.prototype[met] = function() {
        console.log('執行'+met+'方法');
        // 處理單個方法
        if (['get', 'delete', 'head', 'options'].includes(met)) { // 2個參數(url[, config])
            return this.request({
                method: met,
                url: arguments[0],
                ...arguments[1] || {}
            })
        } else { // 3個參數(url[,data[,config]])
            return this.request({
                method: met,
                url: arguments[0],
                data: arguments[1] || {},
                ...arguments[2] || {}
            })
        }

    }
})


// 工具方法,實現b的方法或屬性混入a;
// 方法也要混入進去
const utils = {
  extend(a,b, context) {
    for(let key in b) {
      if (b.hasOwnProperty(key)) {
        if (typeof b[key] === 'function') {
          a[key] = b[key].bind(context);
        } else {
          a[key] = b[key]
        }
      }
      
    }
  }
}


// 最終導出axios的方法-》即實例的request方法
function CreateAxiosFn() {
    let axios = new Axios();

    let req = axios.request.bind(axios);
    // 混入方法, 處理axios的request方法,使之擁有get,post...方法
    utils.extend(req, Axios.prototype, axios)
    return req;
}

// 得到最後的全局變數axios
let axios = CreateAxiosFn();

四、請求和響應攔截器

我們先看下攔截器的使用

// 添加請求攔截器
axios.interceptors.request.use(function (config) {
    // 在發送請求之前做些什麼
    return config;
  }, function (error) {
    // 對請求錯誤做些什麼
    return Promise.reject(error);
  });

// 添加響應攔截器
axios.interceptors.response.use(function (response) {
    // 對響應數據做點什麼
    return response;
  }, function (error) {
    // 對響應錯誤做點什麼
    return Promise.reject(error);
  });

攔截器是什麼意思呢?其實就是在我們發送一個請求的時候會先執行請求攔截器的代碼,然後再真正地執行我們發送的請求,這個過程會對config,也就是我們發送請求時傳送的參數進行一些操作。

而當接收響應的時候,會先執行響應攔截器的代碼,然後再把響應的數據返回來,這個過程會對response,也就是響應的數據進行一系列操作。

怎麼實現呢?需要明確的是攔截器也是一個類,管理響應和請求。因此我們先實現攔截器

class InterceptorsManage {
  constructor() {
    this.handlers = [];
  }

  use(fullfield, rejected) {
    this.handlers.push({
      fullfield,
      rejected
    })
  }
}

我們是用這個語句axios.interceptors.response.useaxios.interceptors.request.use,來觸發攔截器執行use方法的。

說明axios上有一個響應攔截器和一個請求攔截器。那怎麼實現Axios呢?看代碼

class Axios {
    constructor() {
        新增代碼
        this.interceptors = {
            request: new InterceptorsManage,
            response: new InterceptorsManage
        }
    }

    request(config) {
        return new Promise(resolve => {
            const {url = '', method = 'get', data = {}} = config;
            // 發送ajax請求
            console.log(config);
            const xhr = new XMLHttpRequest();
            xhr.open(method, url, true);
            xhr.onload = function() {
                console.log(xhr.responseText)
                resolve(xhr.responseText);
            };
            xhr.send(data);
        })
    }
}

可見,axios實例上有一個對象interceptors。這個對象有兩個攔截器,一個用來處理請求,一個用來處理響應。

所以,我們執行語句axios.interceptors.response.useaxios.interceptors.request.use的時候,實現獲取axios實例上的interceptors對象,然後再獲取response或request攔截器,再執行對應的攔截器的use方法。

而執行use方法,會把我們傳入的回調函數push到攔截器的handlers數組裡。

到這裡你有沒有發現一個問題。這個interceptors對象是Axios上的啊,我們導出的是request方法啊(欸?好熟悉的問題,上面提到過哈哈哈~~~額)。處理方法跟上面處理的方式一樣,都是把Axios上的方法和屬性搬到request過去,也就是遍歷Axios實例上的方法,得以將interceptors對象掛載到request上。

所以只要更改下CreateAxiosFn方法即可。

function CreateAxiosFn() {
  let axios = new Axios();
  
  let req = axios.request.bind(axios);
  // 混入方法, 處理axios的request方法,使之擁有get,post...方法
  utils.extend(req, Axios.prototype, axios)
  新增代碼
  utils.extend(req, axios)
  return req;
}

好了,現在request也有了interceptors對象,那麼什麼時候拿interceptors對象中的handler之前保存的回調函數出來執行。

沒錯,就是我們發送請求的時候,會先獲取request攔截器的handlers的方法來執行。再執行我們發送的請求,然後獲取response攔截器的handlers的方法來執行。

因此,我們要修改之前所寫的request方法 之前是這樣的。

request(config) {
    return new Promise(resolve => {
        const {url = '', method = 'get', data = {}} = config;
        // 發送ajax請求
        console.log(config);
        const xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.onload = function() {
            console.log(xhr.responseText)
            resolve(xhr.responseText);
        };
        xhr.send(data);
    })
}
但是現在request里不僅要執行發送ajax請求,還要執行攔截器handlers中的回調函數。所以,最好下就是將執行ajax的請求封裝成一個方法
request(config) {
    this.sendAjax(config)
}
sendAjax(config){
    return new Promise(resolve => {
        const {url = '', method = 'get', data = {}} = config;
        // 發送ajax請求
        console.log(config);
        const xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.onload = function() {
            console.log(xhr.responseText)
            resolve(xhr.responseText);
        };
        xhr.send(data);
    })
}
好了,現在我們要獲得handlers中的回調
request(config) {
    // 攔截器和請求組裝隊列
    let chain = [this.sendAjax.bind(this), undefined] // 成對出現的,失敗回調暫時不處理

    // 請求攔截
    this.interceptors.request.handlers.forEach(interceptor => {
        chain.unshift(interceptor.fullfield, interceptor.rejected)
    })

    // 響應攔截
    this.interceptors.response.handlers.forEach(interceptor => {
        chain.push(interceptor.fullfield, interceptor.rejected)
    })

    // 執行隊列,每次執行一對,並給promise賦最新的值
    let promise = Promise.resolve(config);
    while(chain.length > 0) {
        promise = promise.then(chain.shift(), chain.shift())
    }
    return promise;
}

我們先把sendAjax請求和undefined放進了chain數組裡,再把請求攔截器的handlers的成對回調放到chain數組頭部。再把響應攔截器的handlers的承兌回調反倒chain數組的尾部。

然後再 逐漸取數 chain數組的成對回調執行。

promise = promise.then(chain.shift(), chain.shift())

這一句,實際上就是不斷將config從上一個promise傳遞到下一個promise,期間可能回調config做出一些修改。什麼意思?我們結合一個例子來講解一下

首先攔截器是這樣使用的

// 添加請求攔截器
axios.interceptors.request.use(function (config) {
    // 在發送請求之前做些什麼
    return config;
  }, function (error) {
    // 對請求錯誤做些什麼
    return Promise.reject(error);
  });

// 添加響應攔截器
axios.interceptors.response.use(function (response) {
    // 對響應數據做點什麼
    return response;
  }, function (error) {
    // 對響應錯誤做點什麼
    return Promise.reject(error);
  });

然後執行request的時候。chain數組的數據是這樣的

chain = [
  function (config) {
    // 在發送請求之前做些什麼
    return config;
  }, 
  
  function (error) {
    // 對請求錯誤做些什麼
    return Promise.reject(error);
  }
  this.sendAjax.bind(this), 
  
  undefined,
  
  function (response) {
    // 對響應數據做點什麼
    return response;
  }, 
  function (error) {
    // 對響應錯誤做點什麼
    return Promise.reject(error);
  }
]

首先

執行第一次promise.then(chain.shift(), chain.shift()),即

promise.then(
  function (config) {
    // 在發送請求之前做些什麼
    return config;
  }, 
  
  function (error) {
    // 對請求錯誤做些什麼
    return Promise.reject(error);
  }
)

一般情況,promise是resolved狀態,是執行成功回調的,也就是執行

function (config) {
    // 在發送請求之前做些什麼
    return config;
  }, 

而promise.then是要返回一個新的promise對象的。

為了區分,在這裡,我會把這個新的promise對象叫做第一個新的promise對象 這個第一個新的promise對象會把

function (config) {
    // 在發送請求之前做些什麼
    return config;
  }, 

的執行結果傳入resolve函數中

resolve(config)

使得這個返回的第一個新的promise對象的狀態為resovled,而且第一個新的promise對象的data為config。

這裡需要對Promise的原理足夠理解。所以我前一篇文章寫的是手寫Promise核心原理,再也不怕面試官問我Promise原理,你可以去看看 接下來,再執行

promise.then(
  sendAjax(config)
  ,
  undefined
)

註意:這裡的promise是 上面提到的第一個新的promise對象。

而promise.then這個的執行又會返回第二個新的promise對象。

因為這裡promise.then中的promise也就是第一個新的promise對象的狀態是resolved的,所以會執行sendAjax()。而且會取出第一個新的promise對象的data 作為config轉入sendAjax()。

當sendAjax執行完,就會返回一個response。這個response就會保存在第二個新的promise對象的data中。

接下來,再執行

promise.then(
  function (response) {
    // 對響應數據做點什麼
    return response;
  }, 
  function (error) {
    // 對響應錯誤做點什麼
    return Promise.reject(error);
  }
)

同樣,會把第二個新的promise對象的data取出來作為response參數傳入

function (response) {
    // 對響應數據做點什麼
    return response;
  }, 

飯後返回一個promise對象,這個promise對象的data保存了這個函數的執行結果,也就是返回值response。

然後通過return promise;

把這個promise返回了。咦?是怎麼取出promise的data的。我們看看我們平常事怎麼獲得響應數據的

axios.get('http://localhost:5000/getTest')
    .then(res => {
         console.log('getAxios 成功響應', res);
    })

在then里接收響應數據。所以原理跟上面一樣,將返回的promise的data作為res參數了。

現在看看我們的myAxios完整代碼吧,好有個全面的瞭解

class InterceptorsManage {
    constructor() {
        this.handlers = [];
    }

    use(fullfield, rejected) {
        this.handlers.push({
            fullfield,
            rejected
        })
    }
}

class Axios {
    constructor() {
        this.interceptors = {
            request: new InterceptorsManage,
            response: new InterceptorsManage
        }
    }

    request(config) {
        // 攔截器和請求組裝隊列
        let chain = [this.sendAjax.bind(this), undefined] // 成對出現的,失敗回調暫時不處理

        // 請求攔截
        this.interceptors.request.handlers.forEach(interceptor => {
            chain.unshift(interceptor.fullfield, interceptor.rejected)
        })

        // 響應攔截
        this.interceptors.response.handlers.forEach(interceptor => {
            chain.push(interceptor.fullfield, interceptor.rejected)
        })

        // 執行隊列,每次執行一對,並給promise賦最新的值
        let promise = Promise.resolve(config);
        while(chain.length > 0) {
            promise = promise.then(chain.shift(), chain.shift())
        }
        return promise;
    }
    sendAjax(){
        return new Promise(resolve => {
            const {url = '', method = 'get', data = {}} = config;
            // 發送ajax請求
            console.log(config);
            const xhr = new XMLHttpRequest();
            xhr.open(method, url, true);
            xhr.onload = function() {
                console.log(xhr.responseText)
                resolve(xhr.responseText);
            };
            xhr.send(data);
        })
    }
}

// 定義get,post...方法,掛在到Axios原型上
const methodsArr = ['get', 'delete', 'head', 'options', 'put', 'patch', 'post'];
methodsArr.forEach(met => {
    Axios.prototype[met] = function() {
        console.log('執行'+met+'方法');
        // 處理單個方法
        if (['get', 'delete', 'head', 'options'].includes(met)) { // 2個參數(url[, config])
            return this.request({
                method: met,
                url: arguments[0],
                ...arguments[1] || {}
            })
        } else { // 3個參數(url[,data[,config]])
            return this.request({
                method: met,
                url: arguments[0],
                data: arguments[1] || {},
                ...arguments[2] || {}
            })
        }

    }
})


// 工具方法,實現b的方法混入a;
// 方法也要混入進去
const utils = {
    extend(a,b, context) {
        for(let key in b) {
            if (b.hasOwnProperty(key)) {
                if (typeof b[key] === 'function') {
                    a[key] = b[key].bind(context);
                } else {
                    a[key] = b[key]
                }
            }

        }
    }
}


// 最終導出axios的方法-》即實例的request方法
function CreateAxiosFn() {
    let axios = new Axios();

    let req = axios.request.bind(axios);
    // 混入方法, 處理axios的request方法,使之擁有get,post...方法
    utils.extend(req, Axios.prototype, axios)
    return req;
}

// 得到最後的全局變數axios
let axios = CreateAxiosFn();
來測試下攔截器功能是否正常
<script type="text/javascript" src="./myAxios.js"></script>

<body>
<button class="btn">點我發送請求</button>
<script>
    // 添加請求攔截器
    axios.interceptors.request.use(function (config) {
        // 在發送請求之前做些什麼
        config.method = "get";
        console.log("被我請求攔截器攔截了,哈哈:",config);
        return config;
    }, function (error) {
        // 對請求錯誤做些什麼
        return Promise.reject(error);
    });

    // 添加響應攔截器
    axios.interceptors.response.use(function (response) {
        // 對響應數據做點什麼
        console.log("被我響應攔截攔截了,哈哈 ");
        response = {message:"響應數據被我替換了,啊哈哈哈"}
        return response;
    }, function (error) {
        // 對響應錯誤做點什麼
        console.log("錯了嗎");
        return Promise.reject(error);
    });
    document.querySelector('.btn').onclick = function() {
        // 分別使用以下方法調用,查看myaxios的效果
        axios({
          url: 'http://localhost:5000/getTest'
        }).then(res => {
          console.log('response', res);
        })
    }
</script>
</body>

攔截成功!!!!!

本文轉載於:

https://juejin.cn/post/6856706569263677447

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 零基礎學MySQL 筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 一個問題 淘寶網,京東、微信,抖音都有各自的功能,那麼當我們退出系統的時候,下次再訪問時,為什麼信息還存在? =》資料庫 解決之道-文件、資料庫 為瞭解決上述問題, ...
  • 案例1:MySQL8.0實現資料庫冷備份和還原 10.0.0.10 -- MySQL8.0 #停止資料庫 [root@CentOS8 my.cnf.d]# systemctl stop mysqld.service #備份數據 [root@CentOS8 ~]# scp -pr /var/lib/m ...
  • 在日常開發工作中,我經常會遇到需要統計總數的場景,比如:統計訂單總數、統計用戶總數等。一般我們會使用MySQL 的count函數進行統計,但是隨著數據量逐漸增大,統計耗時也越來越長,最後竟然出現慢查詢的情況,這究竟是什麼原因呢?本篇文章帶你一下學習一下。 ...
  • 當前伺服器上創建表(單節點) 創建新表具有幾種種語法形式,具體取決於用例。預設情況下,僅在當前伺服器上創建表。分散式DDL查詢作為子句實現,該子句另外描述。 語法形式 使用顯式架構 CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cl ...
  • 摘要:華為雲資料庫助力德邦快遞打造的“基於數智融合的一站式物流供應鏈平臺”項目從500多個項目中脫穎而出,榮獲2022 IDC中國未來企業大獎優秀獎“未來智能領軍者”。 本文分享自華為雲社區《華為雲資料庫助力德邦快遞斬獲IDC中國未來企業大獎“未來智能領軍者”優秀獎》,作者: GaussDB 資料庫 ...
  • “What I cannot create, I do not understand.” – Richard Feynman I’m building a clone of sqlite from scratch in C in order to understand, and I’m going ...
  • 一個沉浸感十足的游戲,其場景中的全局光照效果一定功不可沒。 動態漫反射全局光照(DDGI)帶來的光影變化,是細膩延展的視覺語言,讓場景中每種顏色都有了“五彩斑斕”的詮釋,場景佈局光影,物體關係立顯,環境溫度降臨,拓展了畫面信息傳達的層次,點睛之筆。 直接光渲染 VS 動態漫反射全局光照 細膩的光照視 ...
  • ⚠️1.1萬長文⚠️ React源碼並非洪水猛獸,知道方法,就可以很輕易地馴服它(=^▽^=)。文章基於最新的React源碼進行調試及閱讀,將以通俗地方式解讀React ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...