promise

170 阅读2分钟

/**
 * 一开始,commonjs社区为了异步编程提供了 一种 方案,promise
 * 后来被 es2015 成了一种规范
 *                              fulfilled =》 onfulfilled
 * promise 有pending一种状态,=》
 *                              reject    =》 onRejected
 * 状态是不可逆转的
 * 
*/

/**
 * 1:promise基本用法
*/
const promise = new Promise(function (resolve, reject) {
    // resolve(100) // 承诺达成
    reject(new Error('promise rejected')) // 承诺失败
  })
  
promise.then(function (value) {
    // 即便没有异步操作,then 方法中传入的回调仍然会被放入队列,等待下一轮执行
    console.log('resolved', value)
  }, function (error) {
    console.log('rejected', error)
  })
  console.log('end')
/**
 * 2:promise封装ajax
*/
function ajax(url){
    return new Promise((resolve,reject)=>{
        const xhr = new XMLHttpRequest();
        xhr.open('get',url);
        xhr.onload = function (){
            if (this.status === 200) {
                resolve(this.response);
            }else{
                reject(new Error(this.statusText));
            }
        }
    })
}
ajax('/api/foo.json').then(function (res) {
    console.log(res)
  }, function (error) {
    console.log(error)
  })
/**
 * 3:嵌套使用 Promise 是最常见的误区
*/
ajax('/api/urls.json').then(function (urls) {
  ajax(urls.users).then(function (users) {
    ajax(urls.users).then(function (users) {
      ajax(urls.users).then(function (users) {
        ajax(urls.users).then(function (users) {
        })
      })
    })
  })
})
/**
 * 4:Promise 链式调用,尽可能保持扁平化,避免和上面一样出现回调地狱,它的出现就是为了解决回调地狱;
 * 下一次的then里面的function其实就是上次返回值注册的回调,
 * 上次返回,promise,接受的就是promise的值,
 * 上次return ‘3333’,接受的就是‘3333’,上次返回 rerun null,return undefined,无return ,接受log打印 null,undefined ,undefined;
*/
function ajax (url) {
    return new Promise(function (resolve, reject) {
      resolve({ok:'ok'});
    })
  }
  ajax()
    .then(function (value) {
        console.log('promise',value)//promise { ok: 'ok' }
      return ajax()
    }) // => Promise
    .then(function (value) {
     console.log('promise',value)//promise { ok: 'ok' }
      return 'val';
    }) // => Promise
    .then(function (value) {
      console.log('val',value)//val val
      return null
    }) // => Promise
    .then(function (value) {
      console.log('null:',value)//null: null
      return undefined;
    }) // => Promise
    .then(function (value) {
      console.log('undefined:',value);//undefined: undefined
    })
    .then(function (value) {
        console.log('无return:',value);//无return: undefined
    })
/**
 * 5:错误的捕获
 * 一般要用then,还有尽量不能用全局捕获,最好,每个异常单独捕获;
*/
// Promise 异常处理

function ajax (url) {
    return new Promise(function (resolve, reject) {
      // foo()
      // throw new Error()
      var xhr = new XMLHttpRequest()
      xhr.open('GET', url)
      xhr.responseType = 'json'
      xhr.onload = function () {
        if (this.status === 200) {
          resolve(this.response)
        } else {
          reject(new Error(this.statusText))
        }
      }
      xhr.send()
    })
  }
  
  ajax('/api/users11.json')
    .then(function onFulfilled (value) {
      console.log('onFulfilled', value)
    }, function onRejected (error) {
      console.log('onRejected', error)
    })
  
  // 使用 catch 注册失败回调是更常见的
  
  ajax('/api/users11.json')
    .then(function onFulfilled (value) {
      console.log('onFulfilled', value)
    })
    .catch(function onRejected (error) {
      console.log('onRejected', error)
    })
  
  // then(onRejected) 实际上就相当于 then(undefined, onRejected)
  
  ajax('/api/users11.json')
    .then(function onFulfilled (value) {
      console.log('onFulfilled', value)
    })
    .then(undefined, function onRejected (error) {
      console.log('onRejected', error)
    })
  
  // 同时注册的 onRejected 只是给当前 Promise 对象注册的失败回调
  // 它只能捕获到当前 Promise 对象的异常
  
  ajax('/api/users.json')
    .then(function onFulfilled (value) {
      console.log('onFulfilled', value)
      return ajax('/error-url')
    }, function onRejected (error) {
      console.log('onRejected', error)
    })
  
  // 因为 Promise 链条上的任何一个异常都会被一直向后传递,直至被捕获
  // 分开注册的 onRejected 相当于给整个 Promise 链条注册失败回调
  
  ajax('/api/users.json')
    .then(function onFulfilled (value) {
      console.log('onFulfilled', value)
      return ajax('/error-url')
    }) // => Promise {}
    .catch(function onRejected (error) {
      console.log('onRejected', error)
    })
  
  // 全局捕获 Promise 异常,类似于 window.onerror
  window.addEventListener('unhandledrejection', event => {
    const { reason, promise } = event
  
    console.log(reason, promise)
    // reason => Promise 失败原因,一般是一个错误对象
    // promise => 出现异常的 Promise 对象
  
    event.preventDefault()
  }, false)
  
  // Node.js 中使用以下方式
  process.on('unhandledRejection', (reason, promise) => {
    console.log(reason, promise)
    // reason => Promise 失败原因,一般是一个错误对象
    // promise => 出现异常的 Promise 对象
  })