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

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

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 1. 定義整體結構 先寫出構造函數,將Promise向外暴露 /* 自定義Promise函數模塊:IIFE */ (function (window) { /* Promise構造函數 executor:執行器函數 */ function ...


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

1. 定義整體結構

  1. 先寫出構造函數,將Promise向外暴露
/*
自定義Promise函數模塊:IIFE
 */

(function (window) {
    /*
    Promise構造函數
    executor:執行器函數
     */
    function Promise(executor) {

    }

    // 向外暴露Promise
    window.Promise = Promise
})()
  1. 添加Promise原型對象上的方法
 /*
    Promise原型對象的then
    指定一個成功/失敗的回調函數
    返回一個新的promise對象
     */
    Promise.prototype.then = function(onResolved,onRejected){

    }

    /*
    Promise原型對象的.catch
    指定一個失敗的回調函數
    返回一個新的promise對象
     */
    Promise.prototype.catch = function(onRejected){

    }
  1. 添加Promise函數對象上的方法
/*
    Promise函數對象的resovle方法
    返回一個指定結果的promise對象
     */
    Promise.resolve = function(value){

    }

    /*
    Promise函數對象的reject方法
    返回一個指定reason的失敗狀態的promise對象
    */
    Promise.reject = function(value){

    }

    /*
    Promise函數對象的all方法
    返回一個promise對象,只有當所有promise都成功時返回的promise狀態才成功
    */
    Promise.all = function(0value){

    }

    /*
    Promise函數對象的race方法
    返回一個promise對象,狀態由第一個完成的promise決定
    */
    Promise.race = function(value){

    }

通過上面的註釋可以知道。不管是Promise原型對象上的方法還是Promise函數對象上的方法 ,它們的執行結果都將返回一個Promise對象

2. 實現Promise構造函數

我們看看我們是怎麼使用Promise的

const promiseA = new Promise( (resolve,reject) => {
    resolve(777);
});
  1. 我們傳入了一個函數,而且這個函數被立即執行,不僅如此,這個函數還會立即執行resolve和reject。說明構造函數里有resolve和reject方法。因此我們可以初步實現:
    /*
    Promise構造函數
    executor:執行器函數
     */
    function Promise(executor) {

        function resovle() {

        }
        function reject() {

        }

        // 立即同步執行executor
        executor(resovle,reject)
    }
  1. 每個promise都有一個狀態可能為pending或resolved,rejected。而且初始狀態都為pending。因此需要添加個status來表示當前promise的狀態.。並且每個promise有自己的data。
function Promise(executor) {

        var self = self
        新增代碼
        self.status = 'pending' // 給promise對象指定status屬性,初始值為pending
    
        self.data = undefined // 給promise對象指定一個存儲結果的data

        function resovle() {

        }
        function reject() {

        }

        // 立即同步執行executor
        executor(resovle,reject)
    }

此外,當我們這樣使用Promise的時候,

// 例1
var promise = new Promise((resovle,reject)=>{
    
})

promise.then(resolve=>{},reject=>{})

這時執行到then,因為我們傳入的立即執行函數沒有執行resolve或者reject,所以promise的狀態還是pending,這時要把then裡面的回調函數保存起來,所以需要個callbacks數組

function Promise(executor) {

        var self = self

        self.status = 'pending' // 給promise對象指定status屬性,初始值為pending
        self.data = undefined // 給promise對象指定一個存儲結果的data
        新增代碼
        self.callbacks = []  // 每個元素的結構:{onResolved(){},onRejected(){}}


        function resovle() {

        }
        function reject() {

        }

        // 立即同步執行executor
        executor(resovle,reject)
    }

那 then函數是怎麼把傳入的回調收集起來的。其實很簡單,就是判斷當前promise是否為pending狀態,是的話,就把回調push到callbacks中。

Promise.prototype.then = function(onResolved,onRejected){

        var self = this
        
        if(self.status === 'pending'){
            // promise當前狀態還是pending狀態,將回調函數保存起來
            self.callbacks.push({
                onResolved(){onResolved(self.data)},
                onRejected(){onRejected(self.data)}
            })
        }else if(self.status === 'resolved'){
        }else{
        }

    }
  1. 在上面的例子1的基礎上,當我們執行resovle(value)時,如例2
// 例2
var promise = new Promise((resolve,reject)=>{
    setTimeout(function () {
        resolve(1)
    })
})

promise.then(
    value=>{console.log(value)},
    err=>{console.log(err)}
    )

此時代碼執行情況是怎麼樣的呢?

  1. 先執行new Promise里的代碼,然後發現個定時器,js線程將定時器交給定時器線程處理,2. 然後繼續執行下麵的代碼,發現是then,而且當前的promise還是pending的狀態。就把then里的回調函數放到callbacks中。
  2. 5秒後定時器線程將定時器里的回調函數(也就是巨集任務)放到消息隊列中,js線程在消息隊列里發現了這個巨集任務,就把它拿來執行。
  3. 執行這個巨集任務,就執行了resolve(1),此時promise的callbacks里的回調被執行。並將當前promise狀態改為resolved。然後這個1也會被保存到當前promise對象中

那怎麼實現resolve呢?依舊上面的描述,就知道resovle的功能是執行callbacks里的函數,並保存data並將當前promise狀態改為resolved。所以我們可以這麼實現

function resolve(value) {
    // 將狀態改為resolved
    self.status = 'resolved'
    // 保存value的值
    self.data = value

    // 如果有待執行的callback函數,立即非同步執行回調函數onResolved
    if (self.callbacks.length>0){
        self.callbacks.forEach(callbackObj=>{
            callbackObj.onResolved(value)
        })
    }
}
  1. 我們還知道,promise的狀態只能改變一次,因此當執行resolve的時候要判斷是不是promise是不是pending的狀態,否則是不能執行的
function resolve(value) {
    // 如果當前狀態不是pending,則不執行
    if(this.status !== 'pending'){
        return 
    }
    // 將狀態改為resolved
    this.status = 'resolved'
    // 保存value的值
    this.data = value

    // 如果有待執行的callback函數,立即非同步執行回調函數onResolved
    if (this.callbacks.length>0){
        setTimeout(()=>{
            this.callbacks.forEach(callbackObj=>{ A
                callbackObj.onResolved(value)
            })
        })
    }
}
  1. 異曲同工之妙的是reject方法也是這個道理,因此這裡無需贅述
function reject(value) {
    // 如果當前狀態不是pending,則不執行
    if(self.status !== 'pending'){
        return
    }
    // 將狀態改為rejected
    self.status = 'rejected'
    // 保存value的值
    self.data = value

    // 如果有待執行的callback函數,立即非同步執行回調函數onResolved
    if (self.callbacks.length>0){
      self.callbacks.forEach(callbackObj=>{
          callbackObj.onRejected(value)
      })
    }
}
  1. 我們又知道,當在執行executor的時候,如果執行異常的話,這個promise的狀態會直接執行reject方法。例如
// 例 3
var promise = new Promise((resolve,reject)=>{

    error;執行到這裡出錯了

    setTimeout(function () {
        resolve(1)
    })
})

要實現這個功能,我們可以在executor外讓try catch來捕獲

try{
    // 立即同步執行executor
    executor(resolve,reject)
}catch (e) { // 如果執行器拋出異常,promise對象變為rejected狀態
    reject(e)
}

好了,現在測試下

 // 例4
 let promise = new Promise((resolve,reject)=>{
        
        setTimeout(function () {
            resolve(1)
            //reject(1)
        },100)
    })

    promise.then(
        value=>{
            console.log("onResolved:",value);
        },
        reason=>{
            console.log("onRejected:",reason);
        }
    )

發現成功。 成功輸出onResolved:1

3. 實現then方法

我們在上面簡單的實現了當前promise為pending狀態的情況,如:

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    if(self.status === 'pending'){
        // promise當前狀態還是pending狀態,將回調函數保存起來
        self.callbacks.push({
            onResolved(){onResolved(self.data)},
            onRejected(){onRejected(self.data)}
        })
    }else if(self.status === 'resolved'){
    }else{
    }

}

那其他情況呢?

執行到then時,promise可能會是pending狀態,此時就要把then里的回調函數保存起來,也可能會是resolved或者rejected狀態,此時就不用把回調保存起來,直接執行onResolved或onRejected方法。註意是非同步執行。而且是做為微任務的,這裡我們簡單的用setTimeout來實現就好了。

Promise.prototype.then = function(onResolved,onRejected){

  var self = this

  if(self.status === 'pending'){
      // promise當前狀態還是pending狀態,將回調函數保存起來
      self.callbacks.push({
          onResolved(){onResolved(self.data)},
          onRejected(){onRejected(self.data)}
      })
  }else if(self.status === 'resolved'){
      setTimeout(()=>{
          onResolved(self.data)
      })
  }else{
      setTimeout(()=>{
          onResolved(self.data)
      })
  }

}

而且我們知道,執行完then是要返回一個新的promise的,而新的promise的狀態則由當前then的執行結果來確定。

 Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{
        if(self.status === 'pending'){
            // promise當前狀態還是pending狀態,將回調函數保存起來
            self.callbacks.push({
                onResolved(){onResolved(self.data)},
                onRejected(){onRejected(self.data)}
            })
        }else if(self.status === 'resolved'){
            setTimeout(()=>{
                onResolved(self.data)
            })
        }else{
            setTimeout(()=>{
                onResolved(self.data)
            })
        }
    })

}

當 當前的promise狀態為resolved的時候,則執行then的時候,會執行第二個判斷語句

則當前執行第二個判斷語句的時候會出現三種情況

  1. 如果then里的回調函數返回的不是promise,return的新promise的狀態是則是resolved,value就是返回的值。例如:
// 例5
let promise = new Promise((resolve,reject)=>{
    resolve(1)
})

promise.then(
    value=>{
        return value //返回的不是promise,是value
    }
)

因此,我們可以這樣實現

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{
        if(self.status === 'pending'){
            // promise當前狀態還是pending狀態,將回調函數保存起來
            self.callbacks.push({
                onResolved(){onResolved(self.data)},
                onRejected(){onRejected(self.data)}
            })
        }else if(self.status === 'resolved'){
            修改代碼
            setTimeout(()=>{
                const result = onResolved(self.data)
                if (result instanceof Promise){

                } else {
                // 1. 如果回調函數返回的不是promise,return的promise的狀態是resolved,value就是返回的值。
                    resolve(result)
                }
            })
        }else{
            setTimeout(()=>{
                onResolved(self.data)
            })
        }
    })

}

簡單解釋下:

執行onResolved(self.data),其實就是執行例子中的下麵這個回調函數

value=>{
        return value //返回的不是promise,是value
    }

那麼這個回調函數返回了value。就把value傳入resolve函數,resolve函數將當前新的promise的狀態改為resolved,同時將value保存到當前新的promise的data中。

  1. 如果回調函數返回的是promise,return的promise的結果就是這個promise的結果,如代碼所示,我們返回一個新的promise。如果這個promise執行了resolve,返回的新的promise的狀態則是resolved的。否則為rejected
// 例6
let promise = new Promise((resolve,reject)=>{
    resolve(1)
})

promise.then(
    value=>{
        return new Promise((resolve,reject)=>{
            resolve(2)
            //或者
            //reject(error)
        })
    }
)

因此我們可以這樣實現

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{
        if(self.status === 'pending'){
            // promise當前狀態還是pending狀態,將回調函數保存起來
            self.callbacks.push({
                onResolved(){onResolved(self.data)},
                onRejected(){onRejected(self.data)}
            })
        }else if(self.status === 'resolved'){
            setTimeout(()=>{
                const result = onResolved(self.data)
                if (result instanceof Promise){
                    // 2. 如果回調函數返回的是promise,return的promise的結果就是這個promise的結果
                    result.then(
                        value => {resolve(value)},
                        reason => {reject(reason)}
                    )
                } else {
                    // 1. 如果回調函數返回的不是promise,return的promise的狀態是resolved,value就是返回的值。
                    resolve(result)
                }
            })
        }else{
            setTimeout(()=>{
                onResolved(self.data)
            })
        }
    })

}

在這裡說明一下:

result.then(
    value => {resolve(value)},
    reason => {reject(reason)}
)

由於我們在例6中執行了then里的

value=>{
        return new Promise((resolve,reject)=>{
            resolve(2)
            //或者
            //reject(error)
        })
    }

則返回一個promise對象,這個promise對象可能為resolved狀態(執行 resolve(2))也可能為rejected狀態(執行reject(error))。

將會導致value => {resolve(value)},這個回調函數的執行或者 reason => {reject(reason)}的執行。

因此會把即將返回的新的promise的data設置為value或者,reason。會把狀態設置為resolved或者rejected。

  1. 如果執行這段代碼的時候拋出錯誤,則返回的promise的狀態為rejected,我們可以用try catch來實現
setTimeout(()=>{
    try{
        const result = onResolved(self.data)
        if (result instanceof Promise){
            // 2. 如果回調函數返回的是promise,return的promise的結果就是這個promise的結果
            result.then(
                value => {resolve(value)},
                reason => {reject(reason)}
            )
        } else {
            // 1. 如果回調函數返回的不是promise,return的promise的狀態是resolved,value就是返回的值。
            resolve(result)
        }
    }catch (e) {
      //  3.如果執行onResolved的時候拋出錯誤,則返回的promise的狀態為rejected
        reject(e)
    }
})

異曲同工之妙的是當status === 'rejected',道理一樣

 setTimeout(()=>{
      try{
          const result = onRejected(self.data)
          if (result instanceof Promise){
              // 2. 如果回調函數返回的是promise,return的promise的結果就是這個promise的結果
              result.then(
                  value => {resolve(value)},
                  reason => {reject(reason)}
              )
          } else {
              // 1. 如果回調函數返回的不是promise,return的promise的狀態是resolved,value就是返回的值。
              resolve(result)
          }
      }catch (e) {
          //  3.如果執行onResolved的時候拋出錯誤,則返回的promise的狀態為rejected
          reject(e)
      }
  })

到這裡,我們發現當執行resolve的時候,onResolved(self.data)onRejected(self.data)執行時也會跟上面一樣的結果,可以說執行回調函數都要做以上判斷,因此我們要將

 self.callbacks.push({
    onResolved(){onResolved(self.data)},
    onRejected(){onRejected(self.data)}
})

改成

if(self.status === 'pending'){
// promise當前狀態還是pending狀態,將回調函數保存起來
self.callbacks.push({
    onResolved(){
        try{
            const result = onResolved(self.data)
            if (result instanceof Promise){
                // 2. 如果回調函數返回的是promise,return的promise的結果就是這個promise的結果
                result.then(
                    value => {resolve(value)},
                    reason => {reject(reason)}
                )
            } else {
                // 1. 如果回調函數返回的不是promise,return的promise的狀態是resolved,value就是返回的值。
                resolve(result)
            }
        }catch (e) {
            //  3.如果執行onResolved的時候拋出錯誤,則返回的promise的狀態為rejected
            reject(e)
        }
    },

到此,我們發現,相同的代碼太多了,因此有必要封裝一下

 function handle(callback) {
    try{
        const result = callback(self.data)
        if (result instanceof Promise){
            // 2. 如果回調函數返回的是promise,return的promise的結果就是這個promise的結果
            result.then(
                value => {resolve(value)},
                reason => {reject(reason)}
            )
        } else {
            // 1. 如果回調函數返回的不是promise,return的promise的狀態是resolved,value就是返回的值。
            resolve(result)
        }
    }catch (e) {
        //  3.如果執行onResolved的時候拋出錯誤,則返回的promise的狀態為rejected
        reject(e)
    }
}

這樣以來就清爽了很多

   Promise.prototype.then = function(onResolved,onRejected){

        var self = this

        return new Promise((resolve,reject)=>{
           /*
            調用指定回調函數的處理,根據執行結果。改變return的promise狀態
             */
            function handle(callback) {
                try{
                    const result = callback(self.data)
                    if (result instanceof Promise){
                        // 2. 如果回調函數返回的是promise,return的promise的結果就是這個promise的結果
                        result.then(
                            value => {resolve(value)},
                            reason => {reject(reason)}
                        )
                    } else {
                        // 1. 如果回調函數返回的不是promise,return的promise的狀態是resolved,value就是返回的值。
                        resolve(result)
                    }
                }catch (e) {
                    //  3.如果執行onResolved的時候拋出錯誤,則返回的promise的狀態為rejected
                    reject(e)
                }
            }
            if(self.status === 'pending'){
                // promise當前狀態還是pending狀態,將回調函數保存起來
                self.callbacks.push({
                    onResolved(){
                        handle(onResolved)
                    },
                    onRejected(){
                        handle(onRejected)
                    }
                })
            }else if(self.status === 'resolved'){
                setTimeout(()=>{
                    handle(onResolved)
                })
            }else{ // 當status === 'rejected'
                setTimeout(()=>{
                    handle(onRejected)
                })
            }
        })

    }

另外,我們還知道,promise會發生值傳透,例如

let promsie = new Promise((resolve,reject)=>{
    resolve(1)
})
promsie
  .then(2)
  .then(3)
  .then(value =>console.log(value))

運行結果: 1

解釋:.then 或者 .catch 的參數期望是函數,傳入非函數則會發生值穿透。值傳透可以理解為,當傳入then的不是函數的時候,這個then是無效的。而實際原理上其實是當then中傳入的不算函數,則這個then返回的promise的data,將會保存上一個的promise.data。這就是發生值穿透的原因。而且每一個無效的then所返回的promise的狀態都為resolved

因此,要實現直傳透這個特性,我們可以這樣實現

添加這兩句來判斷要不要發生值傳透

onResolved = typeof onResolved === 'function'? onResolved: value => value
onRejected = typeof onRejected === 'function'? onRejected: reason => {throw reason}

實際上就是改寫,如果傳入的不是函數,那就忽略那個傳入值,自己再寫一個函數。這個函數的執行結果將返回上一個promise的data

Promise.prototype.then = function(onResolved,onRejected){
    onResolved = typeof onResolved === 'function'? onResolved: value => value
    onRejected = typeof onRejected === 'function'? onRejected: reason => {throw reason}
    var self = this

    return new Promise((resolve,reject)=>{

        /*
        調用指定回調函數的處理,根據執行結果。改變return的promise狀態
         */
        function handle(callback) {
            try{
                const result = callback(self.data)
                if (result instanceof Promise){
                    // 2. 如果回調函數返回的是promise,return的promise的結果就是這個promise的結果
                    result.then(
                        value => {resolve(value)},
                        reason => {reject(reason)}
                    )
                } else {
                    // 1. 如果回調函數返回的不是promise,return的promise的狀態是resolved,value就是返回的值。
                    resolve(result)
                }
            }catch (e) {
                //  3.如果執行onResolved的時候拋出錯誤,則返回的promise的狀態為rejected
                reject(e)
            }
        }
        if(self.status === 'pending'){
            // promise當前狀態還是pending狀態,將回調函數保存起來
            self.callbacks.push({
                onResolved(){
                    handle(onResolved)
                },
                onRejected(){
                    handle(onRejected)
                }
            })
        }else if(self.status === 'resolved'){
            setTimeout(()=>{
                handle(onResolved)
            })
        }else{ // 當status === 'rejected'
            setTimeout(()=>{
                handle(onRejected)
            })
        }
    })

}

3.實現catch方法

catch方法的作用跟then里的第二歌回調函數一樣,因此我們可以這樣來實現

Promise.prototype.catch = function(onRejected){
    return this.then(undefined,onRejected)
}

我的天啊,居然這麼簡單

4. 實現Promise.resolve

我們都知道,Promise.resolve方法可以傳三種值

  1. 不是promise
  2. 成功狀態的promise
  3. 失敗狀態的promise
    Promise.resolve(1)
    Promise.resolve(Promise.resolve(1))
    Promise.resolve(Promise.reject(1))

實際上跟實現上面的then時有點像

Promise.resolve = function(value){
  return new Promise((resolve,reject)=>{
      if (value instanceof Promise){
          // 如果value 是promise
          value.then(
              value => {resolve(value)},
              reason => {reject(reason)}
          )
      } else{
          // 如果value不是promise
          resolve(value)
      }

  }

}

5.實現Promise.reject

實現這個比較簡單,返回一個狀態為rejected的promise就好了

/*
Promise函數對象的reject方法
返回一個指定reason的失敗狀態的promise對象
*/
Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason)
    })
}

6.實現Promise.all

我們知道,這個方法會返回一個promise

    /*
    Promise函數對象的all方法
    返回一個promise對象,只有當所有promise都成功時返回的promise狀態才成功
    */
    Promise.all = function(promises){
        return new Promise((resolve,reject)=>{
           
        })
    }
  

而這個promise的狀態由遍歷每個promise產生的結果決定

    /*
    Promise函數對象的all方法
    返回一個promise對象,只有當所有promise都成功時返回的promise狀態才成功
    */
    Promise.all = function(promises){
        return new Promise((resolve,reject)=>{
            // 遍歷promises,獲取每個promise的結果
            promises.forEach((p,index)=>{
                
            })
        })
    }

有兩種結果:

  1. 遍歷到有一個promise是reject狀態,則直接返回的promise狀態為rejected
 Promise.all = function(promises){
        return new Promise((resolve,reject)=>{
            // 遍歷promises,獲取每個promise的結果
            promises.forEach((p,index)=>{
                p.then(
                    value => {
    
                    },
                    reason => { //只要有一個失敗,return的promise狀態就為reject
                        reject(reason)
                    }
                )
            })
        })
    }
  1. 遍歷所有的promise的狀態都為resolved,則返回的promise狀態為resolved,並且還要每個promise產生的值傳遞下去
   Promise.all = function(promises){
      const values = new Array(promises.length)
      var resolvedCount = 0 //計狀態為resolved的promise的數量
      return new Promise((resolve,reject)=>{
          // 遍歷promises,獲取每個promise的結果
          promises.forEach((p,index)=>{
              p.then(
                  value => {
                      // p狀態為resolved,將值保存起來
                      values[index] = value
                      resolvedCount++;
                      // 如果全部p都為resolved狀態,return的promise狀態為resolved
                      if(resolvedCount === promises.length){
                          resolve(values)
                      }
                  },
                  reason => { //只要有一個失敗,return的promise狀態就為reject
                      reject(reason)
                  }
              )
          })
      })
  }

好像可以了,當其實這裡還有一個問題,就是all傳進去的數組不一定都是promise對象,可能是這樣的

all([p,2,3,p])

因此需要把不是promise的數字包裝成promise

    Promise.all = function(promises){
        const values = new Array(promises.length)
        var resolvedCount = 0 //計狀態為resolved的promise的數量
        return new Promise((resolve,reject)=>{
            // 遍歷promises,獲取每個promise的結果
            promises.forEach((p,index)=>{
                Promise.resolve(p).then(
                    value => {
                        // p狀態為resolved,將值保存起來
                        values[index] = value
                        resolvedCount++;
                        // 如果全部p都為resolved狀態,return的promise狀態為resolved
                        if(resolvedCount === promises.length){
                            resolve(values)
                        }
                    },
                    reason => { //只要有一個失敗,return的promise狀態就為reject
                        reject(reason)
                    }
                )
            })
        })
    }

7.實現Promise.race

這個方法的實現要比all簡單很多

  /*
    Promise函數對象的race方法
    返回一個promise對象,狀態由第一個完成的promise決定
    */
    Promise.race = function(promises){
        return new Promise((resolve,reject)=>{
            // 遍歷promises,獲取每個promise的結果
            promises.forEach((p,index)=>{
                Promise.resolve(p).then(
                    value => {
                        // 只要有一個成功,返回的promise的狀態九尾resolved
                        resolve(value)

                    },
                    reason => { //只要有一個失敗,return的promise狀態就為reject
                        reject(reason)
                    }
                )
            })
        })
    }

本文轉載於:

https://juejin.cn/post/6856213486633304078

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

 


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

-Advertisement-
Play Games
更多相關文章
  • 一、 登錄 1.1 登錄預設資料庫 首先切換到oracle用戶,用資料庫預設管理員登錄。 [root@tsm-zh01 ~]# su – oracle [oracle@redhat ~]$ lsnrctl start #開啟監聽 [oracle@tsm-zh01 ~]$ sqlplus / as s ...
  • 對於一個服務端開發來說 MYSQL 可能是他使用最熟悉的資料庫工具,然而,大部分的Java工程師對MySQL的瞭解和掌握程度,大致就停留在這麼一個階段:它可以建庫、建表、建索引,然後就是對裡面的數據進行增刪改查,語句性能有點差?沒關係,在表裡建幾個索引或者調整一下查詢邏輯就可以了,一條sql,MYS... ...
  • 在數字化時代的今天,我們都認同數據會創造價值。為了最大化數據的價值,我們不停的建立著數據遷移的管道,從同構到異構,從關係型到非關係型,從雲下到雲上,從數倉到數據湖,試圖在各種場景挖掘數據的價值。而在這縱橫交錯的數據網路中,邏輯複製扮演著及其重要的角色。 讓我們將視角從複雜的網路拉回其中的一個端點,... ...
  • 2022年9月2日,日本MIC(総務省)發佈了“電波法施行規則等の一部を改正する省令(令和4年総務省令第59號)”省令,更新了Wi-Fi 6E Band 5頻帶5925 ~ 6425 MHz的技術要求。隔天(9月3日),日本DSP機構發佈了“「6GHz帯小電力データ通信システム」の特性試験方法”,為 ...
  • AU上傳ipa出現下圖紅框提示說明成功上傳,如果App Store後臺沒有出現構建版本, 請登錄 apple賬號對應的郵箱查看反饋,特別留意垃圾郵箱,無論成功還是失敗,apple都會發郵件 一、首先登錄iTunes Connect 後臺、查看ipa構建情況 https://appstoreconne ...
  • 現如今,人們在網上聊天、發帖時越來越愛用表情包,表情包一方面是一種個性化的表達方式,另一方面更能傳達出當下的心理活動,可以說在網路社交中表情包是一個不可或缺的存在。加上近年來元宇宙的興起,3D虛擬形象廣泛應用,用戶可以通過自己的表情來控制虛擬形象的表情,做一系列專屬的表情包,更加生動形象。 那麼,如 ...
  • ##vue+element-ui後臺管理系統模板 前端:基於vue2.0+或3.0+加上element-ui組件框架 後端:springboot+mybatis-plus寫介面 通過Axios調用介面完成數據傳遞 通過router路由完成各頁面的跳轉 ###全局配置 App.vue <templat ...
  • 好家伙,繼續優化, 好家伙,我把我的飛機大戰發給我的小伙伴們玩 期待著略微的贊賞之詞,然後他們用手機打開我的給他們的網址 然後點一下飛機就炸了。 游戲體驗零分 (滑鼠點擊在移動端依舊可以生效) 好了所以我們來優化一下這個觸屏移動事件 由於沒有參考,就去翻文檔了 觸摸事件分三個:touchstart、 ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...