promise

本文深入讲解Promise的基本使用、状态变化、常用方法如Promise.all和Promise.race,以及与generator函数的结合,帮助读者掌握异步编程的核心技巧。

Promise

  • 基本使用

    //resolve和reject是JavaScript引擎提供的两个函数
    const promise = new Promise(function(resolve, reject) {
      // ... some code
    
      if (/* 异步操作成功 */){
        resolve(value);
      } else {
        reject(error);
      }
    });
    
    //用then方法分别指定resolved状态和rejected状态的回调函数
    promise.then(function(value) {
      // success
    }, function(error) {
      // failure
    });
    

    then方法可以接受两个回调函数作为参数,第一个回调函数是promise对象的状态变成resolved时调用,第二个回调函数是promise对象的状态变成rejected时调用,第二个函数是可选的,不一定提供。这两个函数都接受promise对象传出的值作为参数。

    function timeout(ms){
        return new Promise((resolve,reject)=>{
            setTimeout(resolve,ms,'done');
        });
    }
    timeout(100).then((value)=>{
        console.log(value);
    });
    

    promise新建后就会立即执行

    let promise = new Promise(function(resolve,reject){
        console.log('Promise');
        resolve();
    });
    promise.then(function(){
        console.log('resolved.');
    });
    console.log('Hi!');
    

    代码执行后,输出顺序如下:

    Promise

    Hi!

    resolved.

    异步加载图片的例子

  function loadImageAsync(url){
      return new Promise(function(resolve,reject){
          const image = new Image();
          image.onload = function(){
              resolve(image);
          };
          
          image.onerror = functioin(){
              reject(new Error('Could not load image at'+url));
          };
          image.src = url;
      });
  }

以上代码,使用Promise包装了一个图片加载的异步操作。如果加载成功,就调用resolve方法,否则就调用reject方法。

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.ststusText));
              }
          };
          cosnt client = new XMLHttpRquest();
          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.log('出错了',error);
  });

getJSON是对XMLHttpRequest对象的封装,用于发出一个针对JSON数据的HTTP请求,并且返回一个promise对象。

一般来说,调用resolve或reject以后,promise的使命就完成了,后续操作应该写在then方法里面,而不是直接写在resolve或reject的后面。所以最好在它们前面加上return语句,这样就不会有意外

  new Promise((resolve,reject)=>{
      return resolve(1);
      //后面的语句不会执行
      console.log(2);
  });
  • 状态

    三种状态:pending(进行中)、fufilled(已成功)、rejected(已失败)

    只能从第一种状态到第二或第三种状态,状态一旦改变,就不会再变了

  • 常用方法

    • Promise.all

    Promise.all方法用于将多个promise实例,包装成一个新的Promise实例。

    const p = Promise.all([p1,p2,p3]);
    

    p的状态由p1p2p3决定,任意一个被rejected,p的状态就会变成rejected,否则会变成fullfilled状态。

    • Promise.race

    Promise.race方法用于将多个promise实例,包装成一个新的Promise实例。

    const p = Promise.race([p1,p2,p3]);
    

    只要p1p2p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

    • promise和generator的结合

      function getFoo(){
          return new Promise(function(resolve,reject){
              resolve('foo');
          });
      }
      const g = function* (){
          try{
              const foo = yield getFoo();
              console.log(foo);
          } catch (e){
              console.log(e);
          }
      }
      function run (generator){
          const it = generator();
          function go(result){
              if(result.done) return result.value;
              return result.value.then(function(value){
                  return go(it.next(value));
              },function(error){
                  return go(it.throw(error));
              });
          }
          go(it.next());
      }
      run(g);
      

​ 以上代码的generator函数g之中,有一个异步操作getFoo,它返回的就是一个promise对象。函数run用来处理这个promise对象,并调用下一个next方法

### Promise 在异步编程中的角色 Promise 是一种用于处理异步操作的解决方案,它在语法上是一个 ES6 的原生对象,代表了未来将要发生的事件,用来传递异步操作的消息。从本质上讲,Promise 是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。 Promise 提供了一个统一的 API,使得各种异步操作可以使用相同的方法进行处理。这意味着无论异步操作的结果是成功还是失败,都可以通过 Promise 的 API 来处理这些结果。 Promise 对象有两个主要的状态变化:从 pending(等待)变为 fulfilled(已成功)或 rejected(已失败)。一旦状态改变,就不会再变,这保证了 Promise 的结果是不可逆的。 下面是一个简单的 Promise 使用示例: ```javascript var p1 = new Promise(function(resolve, reject) { // 异步操作 resolve('OK'); // 或者 reject('Error'); }); p1.then(function(rs) { // 如果 p1 的状态变为 resolved,则执行此函数,并且 rs 会接收到 'OK' }).catch(function(rs) { // 如果 p1 的状态变为 rejected,则执行此函数,并且 rs 会接收到 'Error' }).finally(function() { // 不论 p1 的状态如何,finally 中的函数一定会执行 }); ``` 此外,Promise 还提供了 `Promise.all()` 方法,该方法接收一个 Promise 数组,并返回一个新的 Promise。只有当数组中的所有 Promise 都成功完成时,这个新的 Promise 才会成功,并且其结果是一个包含所有 Promise 结果的数组。 ```javascript let p1 = new Promise((resolve, reject) => { resolve('OK'); }); let p2 = Promise.reject('error'); // 修改为 reject 以展示错误处理 let p3 = Promise.resolve('Oh Year!'); const result = Promise.all([p1, p2, p3]); console.log(result); ``` 在这个例子中,由于 p2 被设置为 rejected,所以整个 Promise.all 的结果也会是 rejected。如果希望即使有一个失败也要继续执行其他 Promise,可以考虑使用 `Promise.allSettled()` 方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值