中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

javascript中的糖衣語法Promise對象怎么使用

發布時間:2022-07-21 13:41:20 來源:億速云 閱讀:160 作者:iii 欄目:開發技術

這篇文章主要講解了“javascript中的糖衣語法Promise對象怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“javascript中的糖衣語法Promise對象怎么使用”吧!

一、Promise的誕生

1、回調地獄

最初javascript的異步實現就是使用回調函數。回調地獄就是:一個函數需要等它的回調函數(或者回調和回調的回調...)執行完畢之后再執行。簡單來說,回調函數里面嵌套回調函數。而因為回調地獄的問題,Promise就出現了。我們看看什么是回調地獄:

// 回調地獄
//地獄回調
setTimeout(function () {  //第一層
    console.log(1);//等4秒打印1,然后執行下一個回調函數
    setTimeout(function () {  //第二層
        console.log(2);//等3秒打印2,然后執行下一個回調函數
        setTimeout(function () {   //第三層
            console.log(3);//等2秒打印3,然后執行下一個回調函數
            setTimeout(function () {   //第四層
                console.log(4);//等1秒打印4
            }, 1000)
        }, 2000)
    }, 3000)
}, 4000)

可看出回調地獄的特點

1.難以復用
2.堆棧信息被斷開
3.借助外層變量

回調地獄是為了讓我們代碼執行順序的一種操作(解決異步),但是它會使我們的可讀性非常差。當你有100個,1000個...,代碼會不斷右移,不夠優雅,也會影響性能。嵌套和縮進只是回調地獄的一個梗而已,它導致的問題遠非嵌套導致的可讀性降低而已。接下里我們今天的目的,就是將上面的回調地獄用Promise解決。

二、Promise的行為

1、Promise的語法

Promise的基本語法:Promise函數接收一個函數作為參數,這個函數有兩個參數,一個是成功函數(resolve),一個是失敗函數(reject)。Promise的.then接收兩個回調函數,一個是成功函數的回調,一個是失敗函數的回調。這兩個函數可選,不一定要提供

//Promise語法
let myPromise = new Promise(function(resolve, reject) {
    // "Producing Code"(可能需要一些時間)
    
      resolve(); // 成功時
      reject();  // 出錯時
    });
    
    // "Consuming Code" (必須等待一個兌現的承諾)
    myPromise.then(
      function(value) { /* 成功時的代碼 */ },
      function(error) { /* 出錯時的代碼 */ }
    );

特別注意:

(1)Promise對象中的狀態不會被外界干擾。狀態的改變取決于異步的操作結果。

(2)Promise對象的狀態一旦被改變,就不會進行再次改變。 例如:

let myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok');//第一次狀態為成功
        reject('no');//不會改變
    })
}).then(
    function (result) { console.log('resolved'); },//成功狀態執行then后面的成功回調函數
    function (error) { console.log('reject'); }
)
//resolved

(3)Promise新建后就會立即執行,Promise后面的.then是一個異步操作,在事件循環中叫做“微任務”。會放在同步代碼后面執行。 例如:

let myPromise=new Promise((resolve,reject)=>{
    console.log('Promise');//1
    resolve();
})
    .then(()=>{//這里是一個異步操作
        console.log('succeed');//3
    })
console.log('Promise resolved');//2
// Promise
// Promise resolved
// succeed

2、Promise的方法

(1)Promise.prototype.then()

then方法的返回結果是新的Promise實例,對象狀態由回調函數的執行結果決定。then方法后面還可以再調用另一個then方法,形成鏈條。采用鏈式的then,可以指定一組按照次序調用的回調函數。

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        //設置 p 對象的狀態為失敗,并設置失敗的值 
        reject("出錯啦!");
    }, 1000)
});
p.then(
    function(value){},
    function(reason){console.log(reason);}
)
.then(()=>{
    console.log(123)
});

(2)Promise.prototype.catch()

catch()用于指定發生錯誤時的回調函數.例如:

const p = new Promise((resolve, reject) => {//p為Promise的實例
    setTimeout(() => {
        //設置 p 對象的狀態為失敗,并設置失敗的值 
        reject("出錯啦!");//reject()方法的作用,等同于拋出錯誤
    }, 1000)
});
// p.then(function(value){},function(reason){
// // console.error(reason); 
// console.log(reason);
// });

p.catch(function (reason) {//相當于上面的.then(...)
    console.log(reason);//捕獲reject狀態的值
});

建議總是使用catch()方法,而不使用then()方法的第二個參數.

catch()還可以這樣使用:

const myPromise = new Promise(function(resolve, reject) {
    throw new Error('出錯啦');//從這拋出錯誤,catch()指定的回調函數也可以捕獲
  });
  promise.catch(function(error) {
    console.log(error);
});

(3)Promise.prototype.finally()

finally()方法用于指定不管 Promise 對象最后狀態如何,都會執行的操作。而且finally方法總是會返回原來的值。舉個例子:

function a(){
    return new Promise((resolve,reject)=>{
        resolve('ok')
    },1000)
}
function b(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            reject('no')
        },1500)
    })
}
function c(){
    setTimeout(()=>{
         console.log('finally');
    },500)
   
}
a()
    .then((res)=>{
        console.log(res);
        return b()
    })
    .catch((err)=>{
        console.log(err);
    })
    .finally(c)//參數不是回調函數,如果是回調函數也不需要帶參

//ok
//no
//finally //說明finally()照樣執行,有打印

(4)Promise.resolve()

將現有對象轉為 Promise 對象,狀態為resolved。舉例如下:

let myString='hello';
console.log(myString);//hello
const myPromise=Promise.resolve(myString)//帶參
//等同于const myPromise=Promise.resolve('hello')
console.log(myPromise);//Promise { 'hello' }
myString=Promise.resolve();//不帶參,直接調用
console.log(myString);//Promise { undefined }
myString.then(result=>{//說明myString已經是Promise對象了,只有Promise對象才有.then
    console.log(result);//undefined
})

(5)Promise.reject()

也會返回一個新的 Promise 實例,該實例的狀態為rejected。簡單舉例:

// 以上代碼等于
const p=new Promise((resolve,reject)=>{
    reject('error')
})
p.catch(error=>{
    console.log(error);//error
})
// 或者
p.then(function(){},function(error){console.log(error);})//error
// 或者
p.then(null,function(error){console.log(error);})//error
// 或者
p.then(undefined,function(error){console.log(error);})//error

(6)Promise.all()

all()是將多個 Promise 實例,包裝成一個新的 Promise 實例。接收一個數組作為參數,數組的每一項都是·Promise對象的實例。如果不是,會通過Promise.resolve()將參數轉為Promise實例,再進行處理。all()用于將多個 Promise 實例,包裝成一個新的 Promise 實例

// promise.all()
const myPromise1=new Promise((resolve,reject)=>{
    resolve('sure');
})
    .then(result=>result)

const myPromise2=new Promise((resolve,reject)=>{
    reject('cancel')
})
    .then(result=>result)
    .catch(error=>error)//myPromise2有自己的catch
//感興趣的小伙伴可以嘗試,如果刪除myPromise2.catch(...)后Promise.all([myPromise1,myPromise2])會如何?

Promise.all([myPromise1,myPromise2])//myPromise1,myPromise2都處于成功狀態
    .then(result=>{console.log(result);})//走這里  [ 'sure', 'cancel' ]
    .catch(error=>{console.log(error);})

(7)Promise.race()

race()是將多個 Promise 實例,包裝成一個新的 Promise 實例。接收一個數組作為參數,數組的每一項都是·Promise對象的實例。如果不是,會通過promise.resolve()將參數轉為Promise實例,再進行處理。只要參數的Promise實例有一個率先改變狀態,則狀態改變。例如:

const myPromise2 = new Promise((resolve, reject) => {
    setTimeout(()=>{
       reject('cancel') 
    },3000)
    //如果將時間改為<2000,Promise.race([myPromise1, myPromise2])走哪一步呢?
    
})
    .then(result => result)
    .catch(error => error)
const myPromise1 = new Promise((resolve, reject) => {
    setTimeout(()=>{
        resolve('sure');
    },2000)//myPromise1比myPromise2更先改變狀態
    
})
    .then(result => result)


Promise.race([myPromise1, myPromise2])
    .then(result => { console.log(result); })//走這里,sure
    .catch(error => { console.log(error); })

簡要說一下const p1=Promise.all([promise1,promise2,promise3]) 和const p2=Promise.race([promise1,promise2,promise3])的區別

--前者Promise的實例狀態都為resolved時,p1調用.then()里面成功時的回調函數;如果實例狀態有一個為rejected,p1調用.then()里面失敗時的函數或者走.catch()

--后者注重時序,如果率先改變狀態的實例為resolved,則p2為reslove狀態;否則,為reject狀態。

三、Promise的場景

1、Ajax請求

<head>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
   <div class="name">
      <audio id="audio" controls></audio>
   </div>
        
   <script>
      function getSong() {
       return new Promise((resolve, reject) => {
       $.ajax({
        url: 'https://www.fastmock.site/mock/c024e8920dd6003c63dcd9ed2bbf6cb9/music/music',
        dataType: 'json',
        success(res) {
            console.log(res);
            url = res[0].url;
        }
    })
      resolve();
    })
  }

            function playSong() {
                let audio = document.getElementById('audio');
                window.addEventListener('click', function () {
                audio.src = url;
                audio.play()
            })

            }
            getSong().then(playSong())
    </script>
</body>

2、文件讀取

// 引入fs模塊
const fs=require('fs');
// 使用Promise封裝
const P=new Promise(function(resolve,reject){
    fs.readFile('./text/2.md',(err,data)=>{
        // 如果地址錯誤,拋出異常
        if(err) reject(err) ;
        
        // 如果成功,輸出內容
        resolve(data);
    });
});

P.then(function(value){
    console.log(value.toString());
},function(reason){
    console.log("defeat!!!!");
});

3、圖片加載

<body>
    <img src="https://cache.yisu.com/upload/information/20220721/112/57791.jpg" alt="風景" id="myImage">

    <script>
        const preloadImage = function (path) {
            return new Promise(function (resolve, reject) {
                const image = new Image();
                // 圖片加載成功
                image.onload=()=>{
                    resolve(image)
                }
                // 圖片加載失敗
                image.onerror=()=>{
                    reject('sorry,cannot loding picture')
                };
                image.src = path;
            });
        };

        // 獲取圖片DOM節點
        var preImage=document.getElementById('myImage')
        // 圖片預加載
        preloadImage('https://cache.yisu.com/upload/information/20220721/112/57792.jpg')
        .then(targetImage=>
            // 點擊頁面切換圖片,讓圖片加載
            window.onclick=function(){
                setTimeout(()=>{
                       preImage.src=targetImage.src
                },1000)
            }
        )

    </script>
</body>

4、函數封裝

//例如將微信小程序里的showModal進行Promise封裝,那么在任何需要用到此函數的直接引入就很方便了
// promise形式 封裝 showModal
export const showModal=({content})=>{
    return new Promise((resolve,reject)=>{
        wx.showModal({
          title:'提示',
          content:content,
            success: (result) => {
                resolve(result);
            },
            fail: (err) => {
                reject(err);
            }
        });
          
    })
}

四、Promise的短板

1.無法取消Promise,一旦新建它就會立即執行,無法中途取消

2.如果不設置回調函數,Promise內部拋出的錯誤,不會反映到外部

3.當處于pending狀態時,無法得知目前進展到哪一個階段,是剛剛開始還是即將完成

感謝各位的閱讀,以上就是“javascript中的糖衣語法Promise對象怎么使用”的內容了,經過本文的學習后,相信大家對javascript中的糖衣語法Promise對象怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长沙市| 定结县| 新龙县| 东宁县| 洛川县| 扶风县| 上蔡县| 天台县| 达拉特旗| 扬中市| 海林市| 满城县| 开江县| 双桥区| 邯郸市| 宁德市| 濮阳县| 喀喇沁旗| 蓝山县| 太白县| 靖远县| 田阳县| 玛沁县| 屯留县| 铜陵市| 齐齐哈尔市| 临颍县| 简阳市| 鹿邑县| 五指山市| 乐山市| 蓝山县| 沂源县| 宣化县| 盐池县| 日土县| 成都市| 登封市| 临漳县| 湖南省| 北安市|