Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise #24

Closed
PolluxLee opened this issue Apr 28, 2018 · 0 comments
Closed

Promise #24

PolluxLee opened this issue Apr 28, 2018 · 0 comments

Comments

@PolluxLee
Copy link
Owner

PolluxLee commented Apr 28, 2018

Promise

  • Promise 三个状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)
  • 状态只能从 pending 变为 fulfilledpending 变为 rejected
  • Promise 对象的状态不受外界影响,只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果
  • 回调函数只接收一个参数
let promise = new Promise((resolve, reject) => {
  let ok = true
  if (ok) resolve('yes')
  else reject('no')
})
promise.then(data => console.log(data))
  .catch(err => console.log(data))

then( ) 函数返回值

  • 返回一个 promise 对象
  • 返回一个同步值(什么也不返回,那就是返回 undefined)

返回 Promise 对象,被下一个 then() 捕获

Promise.resolve()
  .then(_ => new Promise(resolve => resolve('Hi')))
  .then(data => console.log(data))

返回的同步值,被 Promise.resolve() 方法转换

Promise.resolve('Hello')
  .then(data => data)
  .then(data => console.log(data))

//等价于
Promise.resolve('Hello')
  .then(data => Promise.resolve(data))
  .then(data => console.log(data))


//使用 await 关键字直接获取到返回的同步值
let a = await Promise.resolve(1)
  .then(data => data)
console.log(a)

Catch

为什么不建议写 then 的第二个参数而使用 catch ?

  • catch 更接近同步的写法 (try/catch)
  • 可以捕获前面 then 方法抛出的错误
//bad
new Promise((resolve, reject) => { resolve() })
.then(data => { throw new Error('Something wrong!') }, err => { console.log(err) })
//Uncaught (in promise) Error: Something wrong!
//  at Promise.then.data

// good
new Promise((resolve, reject) => { resolve() })
.then(data => { throw new Error('Something wrong!') })
.catch(err => { console.log(err) });
//Error: Something wrong!
//  at Promise.then.data

// good
new Promise((resolve, reject) => { throw new Error('reject') })
.then(data => { throw new Error('Something wrong!') })
.catch(err => { console.log(err) });
//Error: reject
//  at Promise (<anonymous>:1:42)
//  at new Promise (<anonymous>)
//  at <anonymous>:1:1

上面一种写法捕获不到 then 方法的异常,下面的写法在最外层加 catch 能够捕获 promise 中冒泡的异常,也能捕获 then 的异常

Catch 无法捕获异步的异常

Promise.resolve()
  .then(_ => {
    setTimeout(() => {
      throw new Error('the err can not catch');
    }, 1000);
  })
  .catch(err => console.log(err))

// Uncaught Error: the err can not catch
//    at setTimeout (<anonymous>:4:13)

Promise 串行

let images = [
  'http://os5w1n6kc.bkt.clouddn.com/01.jpg',
  'http://os5w1n6kc.bkt.clouddn.com/11.jpg',
  'http://os5w1n6kc.bkt.clouddn.com/10.jpg',
]

let load = src => {
  return new Promise((resolve, reject) => {
    let image = new Image()
    image.onload = _ => {
      //为了测试看效果而加的同步阻塞
      let sum = 0
      for(let i=0; i<9999999; i++) { sum ++ }
      console.log('finish', src)
      return resolve({ src })
    }
    image.onerror = err => {
      console.log('error', src, err)
      return resolve({ src, err })
    }
    image.src = src
  })
}

let loadImages = images => {
  images.reduce(
    (promise, src) => {
      return promise.then(() => load(src))
    }, 
    Promise.resolve()
  ).then(() => {})
  .catch(err => console.log(err))
}

loadImages(images)

等价于

Promise.resolve()
  .then(() => load(images[0]))
  .then(() => load(images[1]))
  .then(() => load(images[2]))
  .then(() => {})
  .catch(err => console.log(err))

Promise 并行

const promises = [1, 2, 3].map(function(el) {
  return new Promise(resolve => {
    //为了测试看效果而加的同步阻塞
    let sum = 0
    for(let i=0; i<9999999; i++) { sum ++ }
    return resolve(el)
  })
});

Promise.all(promises)
  .then(data => {
    // data = [1,2,3]
    console.log(data)
  })
  .catch(err => console.log(err))

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant