Promise的10大知識點!

文摘資訊發表於2020-02-24

Promise的10大知識點!

通知:假期延長到2月2號。
通知:假期延長到2月10號。
通知:假期延長到2月17號。
通知:公司沒有了,不要回來了。

Promise的10大知識點!

Promise的10大知識點!

下面是今天的前端知識

Part 1:

const prom = new Promise((res, rej) => {
  console.log('first');
  res();
  console.log('second');
});
prom.then(() => {
  console.log('third');
});
console.log('fourth');


// first
// second
// fourth
// third

知識點:Promise 建構函式是同步執行,promise.then 是非同步執行。

Part 2:

const prom = new Promise((res, rej) => {
  setTimeout(() => {
    res('success');
  }, 1000);
});
const prom2 = prom.then(() => {
  throw new Error('error');
});


console.log('prom', prom);
console.log('prom2', prom2);


setTimeout(() => {
  console.log('prom', prom);
  console.log('prom2', prom2);
}, 2000);


// prom Promise {<pending>}
// prom2 Promise {<pending>}
// Promise {<resolved>: "success"}
// prom2 Promise {<rejected>: Error: error }

知識點:promise 有三種不同的狀態:pending、fulfilled、rejected,一旦狀態更新,就不再改變,只能從pending->fulfilled 或 pending->rejected 。

Part 3:

const prom = new Promise((res, rej) => {
  res('1');
  rej('error');
  res('2');
});


prom
  .then(res => {
    console.log('then: ', res);
  })
  .catch(err => {
    console.log('catch: ', err);
  });


// then: 1

知識點:一旦 resolve 和 reject 同時存在,只會執行第一個,後面的不再執行。

Part 4:

Promise.resolve(1)
  .then(res => {
    console.log(res);
    return 2;
  })
  .catch(err => {
    return 3;
  })
  .then(res => {
    console.log(res);
  });


// 1
// 2

知識點:每次 promise 呼叫 .then 或 catch 時,都會返回一個新的 promise,從而實現連結呼叫。

Part 4:

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('first')
    resolve('second')
  }, 1000)
})


const start = Date.now()
promise.then((res) => {
  console.log(res, Date.now() - start, "third")
})
promise.then((res) => {
  console.log(res, Date.now() - start, "fourth")
})


// first
// second 1054 third
// second 1054 fourth

知識點:一個 promise .then 或 .catch 可以被多次呼叫,但是此處Promise建構函式僅執行一次。 換句話說,一旦promise 的內部狀態發生變化並獲得了一個值,則隨後對 .then 或 .catch 的每次呼叫都將直接獲取該值。

Part 6:

const promise = Promise.resolve()
  .then(() => {
    return promise
  })
promise.catch(console.error)


// [TypeError: Chaining cycle detected for promise #<Promise>]

知識點:.then 或 .catch 返回的值不能是 promise 本身,否則將導致無限迴圈。

Part 7:

Promise.resolve()
  .then(() => {
    return new Error('error');
  })
  .then(res => {
    console.log('then: ', res);
  })
  .catch(err => {
    console.log('catch: ', err);
  });


// then: Error: error!

知識點:在 .then 或 .catch 中返回錯誤物件不會引發錯誤,因此後續的 .catch 不會捕獲該錯誤物件,您需要更改為以下物件之一:

return Promise.reject(new Error('error'))
throw new Error('error')

因為返回任何非promise值都將被包裝到一個Promise物件中,也就是說,返回 new Error('error') 等同於返回Promise.resolve(new Error('error'))

Part 8:

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)


  // 1

知識點:.then 或 .catch 的引數應為函式,而傳遞非函式將導致值的結果被忽略,例如 .then(2)或 .then(Promise.resolve(3))

Part 9:

Promise.resolve()
  .then(
    function success(res) {
      throw new Error('Error after success');
    },
    function fail1(e) {
      console.error('fail1: ', e);
    }
  )
  .catch(function fail2(e) {
    console.error('fail2: ', e);
  });


//   fail2:  Error: Error after success

知識點:.then 可以接受兩個引數,第一個是處理成功的函式,第二個是處理錯誤的函式。 .catch 是編寫 .then 的第二個引數的便捷方法,但是在使用中要注意一點:.then 第二個錯誤處理函式無法捕獲第一個成功函式和後續函式丟擲的錯誤。 catch 捕獲先前的錯誤。 當然,如果要重寫,下面的程式碼將起作用:

Promise.resolve()
  .then(function success1 (res) {
    throw new Error('success1 error')
  }, function fail1 (e) {
    console.error('fail1: ', e)
  })
  .then(function success2 (res) {
  }, function fail2 (e) {
    console.error('fail2: ', e)
  })

Part 10:

process.nextTick(() => {
  console.log('1')
})
Promise.resolve()
  .then(() => {
    console.log('2')
  })
setImmediate(() => {
  console.log('3')
})
console.log('4');


// 4 1 2 3

知識點:process.nextTick 和 promise.then 都屬於微任務,而 setImmediate 屬於巨集任務,它在事件迴圈的檢查階段執行。 在事件迴圈的每個階段(巨集任務)之間執行微任務,並且事件迴圈的開始執行一次。

Promise的10大知識點!