Promise

165 阅读2分钟

Promise

  • 主要用于异步计算,
  • 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果,避免了回调地狱的发生
  • 可以在对象之间传递和操作promise,帮助我们处理队列

状态

  • pending:初始状态
  • fulfilled:操作成功
  • rejected:操作失败

tips

  1. Promise实例一经创建,执行器立即执行
  2. .then()返回新的promis实例,(注意,不是原来那个Promise实例)
  3. 调用resolve或reject并不会终结 Promise 的参数函数的执行
new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
// 2
// 1
  1. 一般来说,调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。
new Promise((resolve, reject) => {
  return resolve(1);
  // 后面的语句不会执行
  console.log(2);
})

Promise的基本使用和原理

  1. 在.then()中返回新的promise实例
  let p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('hello')
      }, 2000);
    }).then(value => {
      console.log(value)
      return new Promise(resolve => {
        setTimeout(() => {
          resolve('world')
        }, 2000)
      })
    }).then(value => {
      console.log(value + 'world')
    })

  1. 如果Promise.then()的函数里不返回新的Promise会怎么样
    let p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('hello')
      }, 2000);
    }).then(value => {
      console.log(value);
      //立即执行函数
      (function () {
        return new Promise(resolve => {
          setTimeout(() => {
            console.log('mr.laurence')
            resolve('world')
          }, 2000)
        })
      })();
      
      return false
    }).then(value => {
      console.log(value + 'world')
    })

3. .then()里的新声明的promise里有.then()的时候,会等到里面的.then()执行完毕,在执行外面的。

    let p = new Promise(resolve => {
      console.log('Step 1')
      setTimeout(() => {
        resolve(100)
      }, 1000);
    }).then(value => {
    
      return new Promise(resolve => {
        console.log('Step 1-1')
        setTimeout(() => {
          resolve(110)
        }, 1000);
      }).then(value => {
        console.log('Step 1-2')
        return value
      }).then(value => {
        console.log('Step 1-3')
        return value
      })
      
    }).then(value => {
      console.log(value)
      console.log('Step 2')
    })

测试

文章:we have a problem with promises

  1. 在then中返回另有一个promise实例
doSomething().then(function(){
  return doSomethingElse()
}).then(finalHandler)

  1. then中没有返回值
doSomethiing().then(function(){
  doSomethingElse()
}).then(finalHandler)

3.如果then方法接受的不是一个函数,会返回一个空的promise对象,这个promise会被忽略

promise.then(onFulfilled,onRejected) 文档中有明确说明,如果onFulfilled,onRejected这个两个参数都被遗漏或者非函数,会被忽略

doSomething().then(doSomethingElse())
.then(finalHandler)

4.

doSomethiing().then(doSomethingElse)
.then(finalHandler)

错误处理

  1. Promise会自动捕获异常,并交给rejected响应函数

练习

Generator

Promise的应用

三张图片都加载完了之后再渲染到页面

  // 所有图片加载完再添加到页面
  function loadImg (src) {
    return new Promise((resolve, reject) => {
      let img = document.createElement('img')
      img.src = src
      //图片加载完成
      img.onload = function () {
        resolve(img)
      }
      //图片加载失败
      img.onerror = function (error) {
        reject(error)
      }
    })
  }

  function showImg (imgs) {
  	imgs.forEach(function (img) {
  		document.body.appendChild(img)
  	})
  }

  // 多个promise实例
  Promise.all([
  	loadImg('http://i4.buimg.com/567571/dflef0720bea6832.png'),
  	loadImg('http://i4.buimg.com/567571/dflef0720bea6832.png'),
  	loadImg('http://i4.buimg.com/567571/dflef0720bea6832.png')
  ]).then(showImg)

面试题

将原生的ajax封装成promise

function newAjax (method,url){
  const p = new Promise(function(resolve,reject){
     let xhr = XMLHttpRequest ? new XMLHttpRequset() : new ActiveXObject()
     xhr.onreadysatechange = function (){
       if(xhr.readyState === 4){
         if(xhr.status === 200 || xhr.status === 304){
           reslove(JSON.parse(xhr.responseText))
         }else{
           reject(new Error('not found'))
         }
       }
     }
     xhr.open('GET',url,true) 
     xhr.send(null)
  })
}