美文网首页
Promise 对象

Promise 对象

作者: SingleDiego | 来源:发表于2019-08-20 16:17 被阅读0次

    参考原文:http://es6.ruanyifeng.com/#docs/promise




    Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

    从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。




    基本用法

    ES6 规定,Promise 对象是一个构造函数,用来生成 Promise 实例。

    下面代码创造了一个 Promise 实例。

    const promise = new Promise(function(resolve, reject) {
      // ... some code
    
      if (/* 异步操作成功 */){
        resolve(value);
      } else {
        reject(error);
      }
    });
    

    Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolvereject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。

    resolve 函数的作用是,将 Promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。

    reject 函数的作用是,将 Promise 对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

    Promise 实例生成以后,可以用 then 方法分别指定 resolved 状态和 rejected 状态的回调函数。

    promise.then(function(value) {
      // success
    }, function(error) {
      // failure
    });
    

    then 方法可以接受两个回调函数作为参数。第一个回调函数是 Promise 对象的状态变为 resolved 时调用。

    第二个回调函数是 Promise 对象的状态变为 rejected 时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受 Promise 对象传出的值作为参数。




    参考例子

    下面是一个 Promise 对象的简单例子。

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

    上面代码中,timeout 方法返回一个 Promise 实例,表示一段时间以后才会发生的结果。

    过了指定的时间(ms 参数)以后,resolve 函数被执行;Promise 实例的状态变为 resolved,就会触发 then 方法绑定的回调函数。

    第二个例子:

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

    上面代码中,Promise 新建后立即执行,所以首先输出的是 Promise。然后,then 方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以 resolved 最后输出。

    第三个例子是一个用 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);
    });
    

    上面代码中,getJSON 是对 XMLHttpRequest 对象的封装,用于发出一个针对 JSON 数据的 HTTP 请求,并且返回一个 Promise 对象。需要注意的是,在 getJSON 内部,resolve 函数和 reject 函数调用时,都带有参数。

    如果调用 resolve 函数和 reject 函数时带有参数,那么它们的参数会被传递给回调函数。

    reject 函数的参数通常是 Error 对象的实例,表示抛出的错误;resolve 函数的参数一般是获取到的正常的值。




    链式 then

    then 方法返回的是一个新的 Promise 实例(注意,不是原来那个 Promise 实例)。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。

    getJSON("/posts.json").then(function(json) {
      return json.post;
    }).then(function(post) {
      // ...
    });
    

    上面的代码使用 then 方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果(也就是 retuen 的内容)作为参数,传入第二个回调函数。

    下面是一个用链式 then 连续读取 A,B 两个文件的示例:

    const fs = require('fs');
    
    const readFile = (fileName) => {
      return new Promise((resolve, reject) => {
        fs.readFile(fileName, (error, data) => {
          if (error) return reject(error);
          resolve(data);
        });
      });
    };
    
    // 第一个 then 的 data 参数来自 readFile 的 resolve(data)
    // 把 data 字符串化之后打印出来
    readFile('./test-A.txt')
    .then((data) => {
      console.log(data.toString());
    })
    // 第二个 then 再执行一遍 readFile,但文件名换成了 B 文件
    // return 出来的数据来自 readFile 的 resolve(data)
    .then(() => {
      const data = readFile('./test-B.txt');
      return data;
    })
    // 第三个 then 的 data 来自第二个 then 的 return 值
    .then((data) => {
      console.log(data.toString());
    })
    

    相关文章

      网友评论

          本文标题:Promise 对象

          本文链接:https://www.haomeiwen.com/subject/jwxpsctx.html