Promise關鍵問題



1.修改promise的狀態

 let p = new Promise((resolve, reject) => {
            //1. resolve 函數
            // resolve('ok'); // pending   => fulfilled (resolved)
            //2. reject 函數
            // reject("error");// pending  =>  rejected 
            //3. 拋出錯誤
            // throw '出問題了',rejected;
        });

通過throw也可以修改promise狀態

image-20210806001915338

2.能否執行多個回調

let p = new Promise((resolve, reject) => {
   resolve('OK');
});

///指定回調 - 1
p.then(value => {
   console.log(value);
});

//指定回調 - 2
p.then(value => {
   alert(value);
});//都可以執行

3.改變狀態與指定回調的順序

1. 如果先指定的回調, 那當狀態發生改變時, 回調函數就會調用, 得到數據

// 常規: 先指定回調函數, 后改變的狀態
new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1) // 后改變的狀態(同時指定數據), 異步執行回調函數
  }, 1000);
}).then(// 先指定回調函數, 保存當前指定的回調函數
  value => {},
  reason => {console.log('reason', reason)}
)

2. 如果先改變的狀態, 那當指定回調時, 回調函數就會調用, 得到數據

// 如果先改狀態, 后指定回調函數
new Promise((resolve, reject) => {
  resolve(1) // 先改變的狀態(同時指定數據)
}).then(// 后指定回調函數, 同步執行回調函數
  value => {console.log('value2', value)},
  reason => {console.log('reason2', reason)}
)

總結:只有當狀態改變才會執行回調

4.then方法返回promise結果由什么決定

let p = new Promise((resolve, reject) => {
    resolve('ok');
});
//執行 then 方法
let result = p.then(value => {
    // console.log(value);
    //1. 拋出錯誤
    // throw '出了問題';
    //2. 返回結果是非 Promise 類型的對象
    // return 521;
    //3. 返回結果是 Promise 對象
    // return new Promise((resolve, reject) => {
    //     // resolve('success');
    //     reject('error');
    // });
    //不返回,promise的值是undefined
    //返回的是pending狀態的promise,會中斷鏈式調用
}, reason => {
    console.warn(reason);
});
console.log(result);

1.拋出錯誤,then返回的promise對象是rejected

2.promise內部返回結果是非promise對象,return number/string/boolean,then的返回的promise對象是resolve

3.then的promise返回結果是promise對象,由內部返回的promise對象來絕對then的promise對象的狀態

4.then內部不返回值,后面的then調用默認是undefined

5.promise如何串聯多個任務

1.promise的then返回一個promise對象,通過鏈式調用即可

2.通過then串聯同步/異步操作

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
    }, 1000);
});

p.then(value => {
    return new Promise((resolve, reject) => {
        resolve("success");
    });
}).then(value => {
    console.log(value);
}).then(value => {
    console.log(value);
})

6.異常的穿透

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
        // reject('Err');
    }, 1000);
});

p.then(value => {
    // console.log(111);
    throw '失敗啦!';
}).then(value => {
    console.log(222);
}).then(value => {
    console.log(333);
}).catch(reason => {
    console.warn(reason);
});

異常的穿透,在改變狀態之后執行then中的回調,then的返回結果是promise,但是改變了promise的狀態,是rejected,返回的rejected的promise對象直接穿透到catch中

7.如何中斷promise鏈

有且只有一個方式返回一個pending狀態的promise

return new Promise(() => {})

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
    }, 1000);
});

p.then(value => {
    console.log(111);
    //有且只有一個方式
    return new Promise(() => {});
}).then(value => {
    console.log(222);
}).then(value => {
    console.log(333);
}).catch(reason => {
    console.warn(reason);
});

8.錯誤的捕獲

首頁我們先要區分幾個概念:
第一,reject是用來拋出異常的,catch是用來處理異常的;
第二:reject是Promise的方法,而then和catch是Promise實例的方法(Promise.prototype.then 和 Promise.prototype.catch)。

1. 區別

主要區別就是,如果在then的第一個函數里拋出了異常,后面的catch能捕獲到,而then的第二個函數捕獲不到。

catch只是一個語法糖而己 還是通過then 來處理的,大概如下所示字體:

Promise.prototype.catch = function(fn){
    return this.then(null,fn);
}

then的第二個參數和catch捕獲錯誤信息的時候會就近原則,如果是promise內部報錯,reject拋出錯誤后,then的第二個參數和catch方法都存在的情況下,只有then的第二個參數能捕獲到,如果then的第二個參數不存在,則catch方法會捕獲到。

const promise = new Promise((resolve, rejected) => {
    throw new Error('test');
});

//此時只有then的第二個參數可以捕獲到錯誤信息
promise.then(res => {
    //
}, err => {
    console.log(err);
}).catch(err1 => {
    console.log(err1);
});


//此時catch方法可以捕獲到錯誤信息
promise.then(res => {
    //
}).catch(err1 => {
    console.log(err1);
});


//此時只有then的第二個參數可以捕獲到Promise內部拋出的錯誤信息
promise.then(res => {
    throw new Error('hello');
}, err => {
    console.log(err);
}).catch(err1 => {
    console.log(err1);
});

//此時只有then的第二個參數可以捕獲到Promise內部拋出的錯誤信息
promise.then(res => {
    throw new Error('hello');
}, err => {
    console.log(err);
});


//此時catch可以捕獲到Promise內部拋出的錯誤信息
promise.then(res => {
    throw new Error('hello');
}).catch(err1 => {
    console.log(err1);
});

2. 兩個捕獲方法的比較

// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

上面代碼中,第二種寫法要好於第一種寫法,理由是第二種寫法可以捕獲前面then方法執行中的錯誤,也更接近同步的寫法(try/catch)。因此,建議總是使用catch方法,而不使用then方法的第二個參數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM