异步编程之Promise

Promise 简介
Promise 为异步编程提供了一种新的解决方案。
简单说Promise 是一个对象,在创建时结果是未知的,他允许你为异步操作返回成功和失败后的处理方法,这样就可以使异步方法像同步方法样有自己的返回值,只是他的返回值不是立即返回,而是一个代表未来出现结果的Promise对象。
三种状态
pending(待定的)、fulfilled(已解决/以实现)、rejected(已拒绝/没有实现)
三种状态之间的转换
从pending转换成fulfilled、从pending转换成rejected(即从进行中分别转向了成功和失败)。
基本用法

  1. 创建Promise实例
const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
例子: 用Promise对象实现的 Ajax 操作

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});

Promise的原型方法
then(用于指定成功时的回调函数。)、catch(用于指定发生错误时的回调函数。)、

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

finally(指定不管 Promise 对象最后状态如何,都会执行的操作)

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

例子:

   console.log('here we go');
   new Promise(resolve=>{
       setTimeout(()=>{
           resolve('hello');
 },2000);
   }).then(value=>{
       console.log(value+ ' world');
 (function (){
     return new Promise(resolve=>{
         setTimeout(()=>{
             console.log("donna");
             resolve("bangbang");
     },4000)
     });
 }());
return false;
 }).then(value=>{
     setTimeout(()=>{
     console.log(value+ " bingbing");
 },3000)

打印的先后顺序为 here we go 、hello world 、false bingbign、donna
第一个then方法里面返回的Promise实例是在立即执行函数里面的,不是这个then方法的返回值,它的返回值是false,所以它不会等里面的定时器执行完,就跳到了下一个then方法中执行(记得value是上一个then方法返回的false),执行完之后,才去执行上面的定时器中的内容

const promise = new Promise(function(resolve, reject) {
  try {
    throw new Error('test');
  } catch(e) {
    reject(e);
  }
});
promise.catch(function(error) {
  console.log(error);
});
 
// 写法二
const promise = new Promise(function(resolve, reject) {
  reject(new Error('test'));
});
promise.catch(function(error) {
  console.log(error);
});
// 写法三
const promise = new Promise(function(resolve, reject) {
  throw new Error('test');
});
promise.catch(function(error) {
  console.log(error);
});

这三种方法是等价的,从上面我们也可以发现,reject方法的作用等同于抛出错误

resolve()
Promise.resolve()方法:有时需要将现有对象转为Promise对象,Promise.resolve方法就起到这个作用
Promise.resolve等价于new Promise(resolve=>resolve(‘foo’));

Promise.resolve方法的参数分四种情况。

  • 参数是一个Promise实例

    这种情况Promise.resolve将不做任何修改,原封不动地返回这个实例。

  • 参数是一个thenable对象

    thenable对象指的是具有then方法的对象。Promise.resolve方法会将这个对象转为Promise对象,然后立即执行thenable对象的then方法。

//使用Promise.resolve方法
 let thenable = {
     then:function(resolve){
         resolve("donna");
     }
 }
  Promise.resolve(thenable).then(value=>{
     console.log(value);//donna
 });
 //上面的方法类似下面的这样
 new Promise(resolve=>{
     resolve("donna");
 }).then(value=>{
     console.log(value);
 })
  • 参数不是具有then方法的对象,或根本不是对象

如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为resolved

let obj= {
     str:function(){
         console.log(123);
     }
 }
  Promise.resolve(obj).then(value=>{
     console.log(value);//{str:f}
 });

上面的代码生成一个新的Promise对象的实例,由于对象obj不是thenable对象,返回Promise实例的状态从一一生成就是resolved,所以回调函数会立即执行,Promise.resolve方法的参数会同时传给回调函数

  • 不带有任何参数

Promise.resolve方法允许调用时不带参数,直接返回一个resolved状态的Promise对象。所以如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve方法
reject()
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected
注意:Promise.reject()方法的参数会原封不动传给后续方法的参数,这一点与Promise.resolve方法不一致


const thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};
 
Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true

上面代码,Promise.reject方法的参数是一个thenable对象,执行以后,后面的catch方法的参数不是reject抛出的“出错了”这个字符串,而是thenable

例子:立即resolve的Promise对象,实在本轮“事件循环”的结束时,而不是在下一轮“事件循环”的开始时

setTimeout(()=>{
     console.log("weiwei");
 },0);
 let thenable = {
     str:function(){
         console.log(123);
     }
 }
  Promise.resolve(thenable).then(value=>{
     console.log(value);//{str:f}
 });
console.log("hongbao");//hongbao  {str:f}  weiwei

上面的代码中,setTimerout(fn,0),在下一轮“事件循环”开始时执行,Promise.resoolve()在本轮“事件循环”结束时执行,console.log(‘hongbao’)则是立即执行,因此最先输出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值