浪小花 發表於 2020-9-21 09:35:00

Salesforce Javascript(一) Promise 浅谈

<p>本篇参看:</p>
<p>https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise</p>
<p>https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises</p>
<p><img src="https://img2020.cnblogs.com/blog/910966/202009/910966-20200915212131758-1857624258.png"></p>
<p>&nbsp;我们在做lwc开发的时候,必须要查看lwc的开发文档。上图我们可以经常用到,lwc的wire adapter提供的创建记录的方法,我们可以看到return的内容是一个Promise对象,而且文档中涉及到异步创建或者加载文档等方法通常说都返回一个Promise对象,对于前端不好的小伙伴可能想的是, Promise是啥怎么用呢?</p>
<p><strong>一. Promise是什么</strong></p>
<p>说起Promise定义和应用以前,我们先从他的汉语以及日常业务场景进行简单的解释。</p>
<p>Promise 的中文可以解释为承诺,做一个简单的业务场景分析。<br>年会了,老板喝酒的时候和你碰了个杯,小张啊,今年表现不错,10天以后就是绩效评定,今年必须给你升职加薪。</p>
<p>对于此时的你来说,两种想法。</p>
<p>A. 老板这么器重我啊,马上就要升职加薪、迎娶白富美、走上人生巅峰,想想还有点小激动。我要更加努力奋斗balabala。</p>
<p>B. 可能老板喝多了,算了,我还是安安静静的搬好我的砖吧。</p>
<p>所以说承诺可能具有以下的情况。</p>
<p>1. 承诺将给你一个保证,这个保证自己做别人做怎么实行,不清楚也不重要,重要的是他给了你承诺,你可以在这个承诺的基础上做你计划的事情。上面的例子中,老板给了你承诺,不管是HR联系你还是老板找你谈,不重要,重要的是老板给你了一个约定,给你升职加薪。<br>2. 既然是一个承诺,他就会有两种情况,要么遵守,要么违约。<br>3. 虽然我们不知道这个承诺当时的状态,但是我们可以计划一下我们期望从这个承诺达到什么东西,也需要去计划一下如果违背了承诺我们怎么处理。比如涨薪以后买个手机或者出去旅游等等,如果不涨薪就安心搬砖或者跳槽等等。<br>4. 承诺应该具有时效性。老板10天以内没有联系你,半年以后老板想起来了,哎呀,我之前忘了,今年一定要给你升职加薪。这对于你来说已经不重要了,因为已经过了时效,默认就应该认为是违约了。<br>5. 承诺通常都不是当时就一下子做的,通常都应该有一定时间进行异步操作。</p>
<p>&nbsp;所以我们通过中文的了解的现实承诺的场景,去了解一下 js中的Promise的概念。</p>
<p>先看一下MDN上面对于Promise的解释:<strong>Promise&nbsp;</strong>对象用于表示一个异步操作的最终完成 (或失败), 及其结果值.也就是说 Promise通常用于异步操作或者加载资源或者IO等等非同步有阻塞的操作。我们对 Promise有了一个大概的使用场景的了解,那么 Promise如何声明如何使用呢,接下来慢慢展开。先看一下 Promise的声明</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">new</span> Promise( <span style="color: rgba(0, 0, 255, 1)">function</span>(resolve, reject) {...} <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> executor </span><span style="color: rgba(0, 128, 0, 1)">*/</span>);</pre>
</div>
<p>参数是一个叫做 executor的函数,包括了两个参数, resolve 以及reject,当然这两个参数也都是函数。当 Promise创建以后,会立即执行&nbsp; executor函数,此时的状态为pending,executor通常操作异步函数,当异步的结果回来有两种可能,成功或者失败。成功的情况下会回调 resolve并且将promise的状态更改为<em>fulfilled,</em>失败的情况下会将Promise的状态更改为rejected并且调用 reject函数,如果异步抛出了异常,则Promise的状态变成 rejected,executor的返回值将被忽略。</p>
<p>这样描述乱乱的,将这个分拆一些细节点。</p>
<p>1.&nbsp; Promise只拥有三种状态: pending (初始状态)、 fulfilled(操作成功)、rejected(操作失败)。其中fulfilled &amp; rejected也可以概括成settled(已定型)。</p>
<p>2.&nbsp;&nbsp;<code>Promise</code>&nbsp;对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。</p>
<p>Promise最终只允许两个结果: pending -&gt; fulfilled 或者是 pending -&gt; rejected。Promise方法封装了一个 then方法,包括两个参数, onfulfilled以及onRejected,这两个参数都是函数类型,当 pending -&gt; fulfilled ,会调用 onfulfilled函数,当pending -&gt; rejected,则会调用 onRejected函数。</p>
<p><img src="https://img2020.cnblogs.com/blog/910966/202009/910966-20200919133551202-1348216025.png">通过这张图可以看出来, Promise不管是执行了 onFulfillment还是 onRejection,返回的类型仍然是 Promise,这就意味着,可以进行多个 Promise的套用。我们在lwc中通常也会遇见多个调用的方式,比如 通过 getRecord获取 account 以后,理论上返回一个 Promise,我们在 then操作时,可以继续请求后台,去获取 关联的Opportunity等等,Promise可以实现俄罗斯套娃方式的调用。</p>
<p><img src="https://img2020.cnblogs.com/blog/910966/202009/910966-20200919133225836-1787937834.png"></p>
<p>解释的很难以理解,来个例子简单了解一下。方法中我们声明了一个Promise,在函数中,调用了 resolve,为了模拟异步操作,使用定时器模拟一下,然后调用 then函数去打印输出。</p>
<div class="cnblogs_code">
<pre>let promise = <span style="color: rgba(0, 0, 255, 1)">new</span> Promise(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(resolve,reject) {
    setTimeout(() </span>=&gt; resolve(2),1000<span style="color: rgba(0, 0, 0, 1)">);
});
promise.then((res) </span>=&gt; console.log(res));</pre>
</div>
<p>结果如下:初始化的时候, Promise是 Pending状态,当1秒以后,调用了 resolve方法,所以输出了2, 此时 promise的状态应该是 fulfilled。</p>
<p><img src="https://img2020.cnblogs.com/blog/910966/202009/910966-20200919135712502-2093699971.png"></p>
<p>&nbsp;再来看一下reject的效果</p>
<div class="cnblogs_code">
<pre>let promise = <span style="color: rgba(0, 0, 255, 1)">new</span> Promise(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(resolve,reject) {
    setTimeout(() </span>=&gt; reject(2),1000<span style="color: rgba(0, 0, 0, 1)">);
});
promise.then((res) </span>=&gt; console.log(res));</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/910966/202009/910966-20200919143122614-319455056.png"></p>
<p>&nbsp;上图中我们还截图了Promise的方法,Promise原型的方法返回的仍然是 Promise,有三个方法可供选择:then/ catch/ finally。举个例子更好的了解。我们针对 Promise也通常这么书写。</p>
<div class="cnblogs_code">
<pre>let bossPromise = <span style="color: rgba(0, 0, 255, 1)">new</span> Promise(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(resolve, reject) {
resolve({
      title: </span>"TL"<span style="color: rgba(0, 0, 0, 1)">,
      increase: </span>"1000"<span style="color: rgba(0, 0, 0, 1)">
    });
});
bossPromise.then(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(result) {
console.log(</span>"哇,我涨薪了,好开心啊 ,老板说我涨了" +<span style="color: rgba(0, 0, 0, 1)"> JSON.stringify(result));
});
bossPromise.</span><span style="color: rgba(0, 0, 255, 1)">catch</span>(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(reason) {
console.log(</span>"没有涨薪,因为老板说我:" +<span style="color: rgba(0, 0, 0, 1)"> reason);
});
bossPromise.</span><span style="color: rgba(0, 0, 255, 1)">finally</span>(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
console.log(</span>"涨与不涨都能接受,我都爱公司和这份工作"<span style="color: rgba(0, 0, 0, 1)">);
});</span></pre>
</div>
<p>结果展示:通过截图可以看到,Promise调用了 resolve,状态变成了fulfilled,调用了 then函数,需要注意的是,不管调用了 then还是catch,都需要调用 finally函数。</p>
<p><img src="https://img2020.cnblogs.com/blog/910966/202009/910966-20200919150050778-682057475.png"></p>
<p>reject相关的操作:</p>
<div class="cnblogs_code">
<pre>let bossPromise = <span style="color: rgba(0, 0, 255, 1)">new</span> Promise(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(resolve, reject) {
reject({
      reason : </span>'能力还得慢慢提高'<span style="color: rgba(0, 0, 0, 1)">
    });
});
bossPromise.then(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(result) {
console.log(</span>"哇,我涨薪了,好开心啊 ,老板说我涨了" +<span style="color: rgba(0, 0, 0, 1)"> JSON.stringify(result));
});
bossPromise.</span><span style="color: rgba(0, 0, 255, 1)">catch</span>(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(reason) {
console.log(</span>"没有涨薪,因为老板说我:" +<span style="color: rgba(0, 0, 0, 1)"> JSON.stringify(reason));
});
bossPromise.</span><span style="color: rgba(0, 0, 255, 1)">finally</span>(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
console.log(</span>"涨与不涨都能接受,我都爱公司和这份工作"<span style="color: rgba(0, 0, 0, 1)">);
});</span></pre>
</div>
<p>结果展示:</p>
<p><img src="https://img2020.cnblogs.com/blog/910966/202009/910966-20200919151735832-914614514.png"></p>
<p>看到了 then catch操作是不是想象到了 当我们调用后台方法的语法,会有 then 和catch,想的没错,这个操作也是基于 Promise实现。</p>
<p><strong>&nbsp;二. Promise在lwc中的使用</strong></p>
<p>前面说过,Promise主要用于异步或者加载资源,因为异步lwc已经封装好了,所以说我们在lwc中使用 Promise大部分是加载资源用。比如我们需要使用外部的css / javascript。上传到 static resource以后,如何引入使之在lwc中有效呢?下面的步骤展示如何加载css或者js资源的步骤。</p>
<p>1. 引入&nbsp;<code class=" language-javascript">loadScript或者<span class="token punctuation">loadStyle用于javascript / css资源;</span></code></p>
<div class="cnblogs_code">
<pre>import { loadScript, loadStyle } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">lightning/platformResourceLoader</span><span style="color: rgba(128, 0, 0, 1)">'</span>;</pre>
</div>
<p><span class="token punctuation">2.从static resource引入相关的资源</span></p>
<div class="cnblogs_code">
<pre>import xxx <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@salesforce/resourceUrl/xxx</span><span style="color: rgba(128, 0, 0, 1)">'</span>;</pre>
</div>
<p>3. 使用 Promise.all用来执行一组 Promise, loadScript / loadStyle是lwc封装好的方法,用来执行 Promise并且返回类型也是 Promise。 Promise.all方法详情可以查看上面的连接。我们只需要 renderedCallback调用 Promise.all即可。详情参看:https://developer.salesforce.com/docs/component-library/documentation/en/lwc/js_third_party_library总方法如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> libsD3.js</span><span style="color: rgba(0, 128, 0, 1)">
/*</span><span style="color: rgba(0, 128, 0, 1)"> global d3 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
import { LightningElement } from </span>'lwc'<span style="color: rgba(0, 0, 0, 1)">;
import { ShowToastEvent } from </span>'lightning/platformShowToastEvent'<span style="color: rgba(0, 0, 0, 1)">;
import { loadScript, loadStyle } from </span>'lightning/platformResourceLoader'<span style="color: rgba(0, 0, 0, 1)">;
import D3 from </span>'@salesforce/resourceUrl/d3'<span style="color: rgba(0, 0, 0, 1)">;
import DATA from </span>'./data'<span style="color: rgba(0, 0, 0, 1)">;

export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> class LibsD3 extends LightningElement {
    svgWidth </span>= 400<span style="color: rgba(0, 0, 0, 1)">;
    svgHeight </span>= 400<span style="color: rgba(0, 0, 0, 1)">;

    d3Initialized </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;

    renderedCallback() {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.d3Initialized) {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      }
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.d3Initialized = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;

      Promise.all([
            loadScript(</span><span style="color: rgba(0, 0, 255, 1)">this</span>, D3 + '/d3.v5.min.js'<span style="color: rgba(0, 0, 0, 1)">),
            loadStyle(</span><span style="color: rgba(0, 0, 255, 1)">this</span>, D3 + '/style.css'<span style="color: rgba(0, 0, 0, 1)">)
      ])
            .then(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.initializeD3();
            })
            .</span><span style="color: rgba(0, 0, 255, 1)">catch</span>(error =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.dispatchEvent(
                  </span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ShowToastEvent({
                        title: </span>'Error loading D3'<span style="color: rgba(0, 0, 0, 1)">,
                        message: error.message,
                        variant: </span>'error'<span style="color: rgba(0, 0, 0, 1)">
                  })
                );
            });
    }

    initializeD3() {
      console.log(</span>'test'<span style="color: rgba(0, 0, 0, 1)">);
    }
}</span></pre>
</div>
<p><strong>总结:</strong>篇中只是简单描述Promise的介绍以及使用,有错误地方欢迎指出,有不懂欢迎留言。</p>

</div>
<div id="MySignature" role="contentinfo">
    <p>作者:zero</p>
<p>博客地址:http://www.cnblogs.com/zero-zyq/</p>
<p>本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接 </p>
<p>如果文章的内容对你有帮助,欢迎点赞~</p>
<p>为方便手机端查看博客,现正在将博客迁移至微信公众号:<strong>Salesforce零基础学习</strong>,欢迎各位关注。</p><br><br>
来源:https://www.cnblogs.com/zero-zyq/p/13675750.html
頁: [1]
查看完整版本: Salesforce Javascript(一) Promise 浅谈