快速将 Promise 运用在开发中

sunny冰青 8年前
   <p>这篇文章面向对Promise不甚了解的朋友,我将告诉你如何把它快速运用在开发中。</p>    <h3>什么是Promise?</h3>    <p>简单几句介绍一下。Promise是抽象异步处理对象以及对其进行各种操作的组件。你可以理解为:它的出现,是为了让我们更方便的进行异步处理。</p>    <p>在Promise出现之前,说到JavaScript的异步处理,我们都会想到回调函数,like this:</p>    <pre>  <code class="language-javascript">getAsync("fileA.txt", function(error, result){    if(error){// 取得失败时的处理 throw error;      throw error;    }  });</code></pre>    <p>上面遵循 Node.js 的规定,回调的第一个参数是 error 。如果所有的回调函数都像 Node.js 一样,统一参数使用规则的话,那写法会很明了,但也仅仅是编码规范而已,使用不同的写法也不会出错。</p>    <p>而Promise则是把异步处理对象和处理规则进行规范化,并采用统一的接口来编写,使用规定方法之外的写法都会出错。</p>    <p>我们可以先看一个简单的使用Promise进行异步处理的例子:</p>    <pre>  <code class="language-javascript">var promise = getAsyncPromise("fileA.txt");    promise.then(function(result){    // 获取文件内容成功时的处理  }).catch(function(error){    // 获取文件内容失败时的处理  });</code></pre>    <p>看上去和回调函数有些不一样,在使用Promise进行异步处理的时候,我们必须按照接口规定的方法编写处理代码。</p>    <p>也即是说,除了使用Promise规定的方法(上面的 then 和 catch ),其他的方法都是不能使用的,而回调函数可以自定义回调的参数。</p>    <p>所以,Promise可以将复杂的异步处理轻松的进行模式化,没有理由让你不使用它。</p>    <p>接下来,我们看看怎么把Promise运用到开发中,这个才是大家想了解的。</p>    <h3>学习Promise</h3>    <p>在运用到开发之前,我们有必要先学习一些Promise的基本API(暂时看的有点糊涂没关系,等会的例子实践会和大家讲清楚的)。</p>    <p>目前大致有下面三种类型:</p>    <p>1.Constructor(构造器)</p>    <p>我们从构造函数 Promise 来创建一个新 promise 对象作为接口。</p>    <p>要创建一个 promise 对象,可以使用 new 来调用 Promise 构造器来进行实例化。</p>    <pre>  <code class="language-javascript">var promise = new Promise(function(resolve, reject) { // 异步处理    // 处理结束后、调用resolve 或 reject  });</code></pre>    <p>2.Instance Method(实例方法)</p>    <p>在通过 new 生成的 promise 对象时,我们设置了在resolve(成功)和reject(失败)时调用的回调函数,我们可以使用 promise.then() 实例方法。</p>    <pre>  <code class="language-javascript">promise.then(onFulfilled,onReject);</code></pre>    <ul>     <li> <p>resolve(成功)时: onFulfilled 会被调用</p> </li>     <li> <p>reject(失败)时: onReject 会被调用</p> </li>    </ul>    <p>onFulfilled 和 onReject 都为可选参数</p>    <p>promise.then 成功和失败时都可以使用,另外在异常处理时,可以使用 promise.then(undefined, onReject) 这种方式,只指定 reject 时的回调函数即可。不过这种情况下,使用 promise.catch() 是个明智之选。</p>    <pre>  <code class="language-javascript">promise.catch(onReject);</code></pre>    <p>3.Static Method(静态方法)</p>    <p>像 promise.all() 和 Promise.resolve() 等在内,主要都是一些辅助方法(可以理解为一些语法糖),这里不作深入探讨。</p>    <h3>运用在开发中</h3>    <p>我们先来看一段Promise使用流程代码:</p>    <pre>  <code class="language-javascript">function asyncFunction() {  //(1)    return new Promise(function(resolve, reject) {      setTimeout(function() {        resolve('Async Hello World');      }, 300);    });  }    asyncFunction().then(function(value) {  //(2)    console.log(value); //300ms后打印 "Async Hello World"  }).catch(function(error) {  //(3)    console.log(error);  })</code></pre>    <p>分析一下上面代码。</p>    <p>执行 (1) 处函数,会返回一个Promise对象,Promise对象内部在300ms后执行 resolve() 方法,这个方法调用 (2) 处的 then() 方法,并传入参数,如果Promise对象内部出现任何错误(比如平台不支持setTimeout方法),就会执行 (3) 处的 catch() 发放,并把错误作为参数传入。</p>    <p>这里提一下,我看到很多朋友把Promise理解为Ajax的一种扩展,其实并不是这样的,Ajax只是一种请求数据的方式,因为Ajax是异步的,所以我们可以用Promise去管理Ajax请求,但这并不意味这Promise只服务于Ajax,只要是异步处理,我们都可以使用Promise去处理,就比如上面的 setTimeout 。</p>    <p>看到这里大家对Promise应该有一个大概的认识了,实际开发中Promise大部分时间还是搭配Ajax使用,我们来看看应该怎么做,下面用原生的方式请求Ajax,大家也温习一下:</p>    <pre>  <code class="language-javascript">function getURL(URL) {    return new Promise(function(resolve, reject) {      var req = new XMLHttpRequest();        req.open('GET', URL, true);        req.onload = function() {        if (req.status === 200) {          resolve(req.responseText);        }else {          reject(new Error(req.statusText));        }      };        req.onerror = function() {        reject.(new Error(req.statusText));      };        req.send();    });  }    // 运行示例  var URL = "https://rockjins.js.org";  getURL(URL).then(function onFulfilled(value){    console.log(value);  }).catch(function onRejected(error){    console.error(error);  });</code></pre>    <p>getURL 只有在XHR取得状态为200时才会调用 resolve ,也就是数据取得成功时,而其他情况(数据取得失败)则会调用 reject 。</p>    <p>当调用 resolve(req.responseText) 时, then 方法也会被调用,并接收到 req.responseText 参数。</p>    <p>熟悉Node.js的朋友在写回调时会会将 callback(error,response) 的第一个参数设为 error 对象,在Promise中,resolve(成功)/reject(失败)担当了这个职责。</p>    <p>XHR中 onerror 触发时,就是发生错误时,理所当然要调用 reject ,我们重点来看下传给 reject 的值。</p>    <p>发生错误时要像这样 reject(new Error(req.statusText)) ,创建一个Error对象再讲具体的值传入进去。传给 reject 的值也没有什么特殊限制,一般只要是Error对象(或继承自Error对象)即可。</p>    <h3>小结</h3>    <p>其实你理解了Promise的运作流程,使用它十分方便和简单,它就是一个异步管理器,帮助我们更好地去进行异步处理。</p>    <p>试想,如果Promise真的很复杂,那它出现的意义是什么?本末倒置了,哈哈。</p>    <p> </p>    <p> </p>    <p>来自:https://juejin.im/post/58c5a621570c35006d66eee9</p>    <p> </p>