目錄
#回呼地獄" >#回呼地獄
首頁 web前端 js教程 一文帶你輕鬆掌握Promise

一文帶你輕鬆掌握Promise

Feb 10, 2023 pm 07:49 PM
javascript promise

一文帶你輕鬆掌握Promise

前端js學習中,讓大家最難受的就是異步的問題,解決異步、回調地獄等問題時你必須得學會promise,對於多數前端程式設計師來說promise簡直就是惡夢,這篇文章就是從簡單易懂的角度做為切入點,幫助大家輕鬆掌握promise

非同步程式設計


#想要學習promise,你必須懂得什麼是非同步程式設計!眾所周知,js語言是單執行緒機制。所謂單線程就是按次序執行,執行完一個任務再執行下一個。但是不影響存在同步異步的兩種操作,這兩種操作做事情其實都是在一條流水線上(單線程),只是這兩種操作在單線程上的執行順序不一樣罷了!當js觸發到非同步任務時,會將非同步任務交給瀏覽器處理,當執行有結果時,會把非同步任務的回呼函數插入待處理佇列的隊尾!

我們通俗的去解釋一下我們的非同步:非同步就是從主執行緒發射一個子執行緒來完成任務,每一個任務都有一個或多個回呼函數(callback ),前一個任務結束後,不是執行後一個任務,而是執行回呼函數後一個任務則是不等前一個任務結束就執行,所以程式的執行順序與任務的排列順序是不一致的、異步的.

一文帶你輕鬆掌握Promise

該圖摘自於菜鳥教程中的非同步編程小節,幫助大家更好的理解什麼是異步!

回呼函數


#回呼函數的定義非常簡單:一個函數被當作一個實參傳入到另一個函數(外部函數),而這個函數在外部函數內被調用,用來完成某些任務的函數。就稱為回呼函數

回呼函數的兩種寫法(實作效果相同):

const text = () => {
	   document.write('hello james')
}
setTimeout(text,1000)
登入後複製
setTimeout(()=>{
	   document.write("hello james")
},1000)
登入後複製

這段程式碼中的setTimeout 就是一個消耗時間較長的過程,它的第一個參數是個回呼函數,第二個參數是毫秒數,這個函數執行之後會產生一個子線程,子線程會等待1 秒,然後執行回呼函數"text",在文字中輸出hello james

setTimeout會在子線程中等待1秒,但是主執行緒的運行不會受到影響!例如以下程式碼:

setTimeout(()=>{
    document.write("hello davis")
},1000)
console.log('123456');
登入後複製

在這裡會先列印出來123456(主執行緒),然後一秒鐘後在文字中輸出hello davis(子執行緒)

#回呼地獄


##回呼地獄這個詞聽起來就非常的高大上,想要接觸Promise之前,必須懂得什麼是

回調地獄,以及為什麼會產生回調地獄? 先來看看概念:
當一個回呼函數嵌套一個回呼函數的時候就會出現一個巢狀結構當巢狀的多了就會出現回呼地獄的情況
舉個例子#我們發送三個ajax 請求:

    #第一個正常發送
  • ##第二個請求需要第一個請求的結果中的某一個值作為參數
  • 第三個請求需要第二個請求的結果中的某一個值作為參數
你會看到以下程式碼

$.ajax({
  url: '我是第一个请求',
  type: 'get',
  success (res) {
    // 现在发送第二个请求
    $.ajax({
      url: '我是第二个请求',
      type:'post',
      data: { a: res.a, b: res.b },
      success (res1) {
        // 进行第三个请求
        $.ajax({
          url: '我是第三个请求',
          type:'post',
          data: { a: res1.a, b: res1.b },
                  success (res2) { 
            console.log(res2) 
          }
        })
      }
    })
  }
})
登入後複製

這種程式碼看起來屬實是折磨人啊!當我們把程式碼寫成這樣的時候,就陷入了
可維護性差

的狀態了,程式碼體驗非常的不良好,看一會就給看懵了,為了解決這個問題,於是,就引入了我們的Promise,用Promise去解決回調地獄問題!

Promise


#Promise

非同步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大,它是一個ECMAScript 6 提供的類別,目的是更加優雅地書寫複雜的非同步任務
Promise物件有以下兩個特點:

    物件的狀態不受外界影響。 Promise物件代表一個非同步操作,有三種狀態:
  • pending

    (進行中)、fulfilled(已成功)和rejected(已失敗)。 只有非同步操作的結果,可以決定目前是哪一種狀態,任何其他操作都無法改變這個狀態。這也是Promise這個名字的由來,它的英文意思是「承諾」,表示其他手段無法改變。 </li><li><p><code>一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

两个特点摘自于??阮一峰ES6文章

Promise语法格式

new Promise(function (resolve, reject) {
  // resolve 表示成功的回调
  // reject 表示失败的回调
}).then(function (res) {
  // 成功的函数
}).catch(function (err) {
  // 失败的函数
})
登入後複製

出现了new关键字,就明白了Promise对象其实就是一个构造函数,是用来生成Promise实例的。能看出来构造函数接收了一个函数作为参数,该函数就是Promise构造函数的回调函数,该函数中有两个参数resolvereject,这两个参数也分别是两个函数!

简单的去理解的话resolve函数的目的是将Promise对象状态变成成功状态,在异步操作成功时调用,将异步操作的结果,作为参数传递出去。reject函数的目的是将Promise对象的状态变成失败状态,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

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

代码示例:

        const promise = new Promise((resolve,reject)=>{
            //异步代码
            setTimeout(()=>{
                // resolve([&#39;111&#39;,&#39;222&#39;,&#39;333&#39;])
                reject(&#39;error&#39;)
            },2000)
        })
        promise.then((res)=>{
            //兑现承诺,这个函数被执行
            console.log(&#39;success&#39;,res);
        }).catch((err)=>{
            //拒绝承诺,这个函数就会被执行
            console.log(&#39;fail&#39;,err);
        })
登入後複製

代码分析:

上边说到Promise是一个构造函数,new之后等于说调用了构造函数,构造函数中传的参数是一个函数,这个函数内的两个参数分别又是两个函数(reslovereject),虽然感觉很绕,但是理清思路会很清晰的!


我们得到对象promise,promise对象中自带有两个方法thencatch,这两个方法中会分别再传入一个回调函数,这个回调函数的目的在于返回你所需要成功或失败的信息!那么怎么去调用这两个回调函数呢?
看下方图可以快速理解:

一文帶你輕鬆掌握Promise
这两个函数分别做为参数(reslovereject)传到上方的函数中去了.随后在构造函数的回调函数中写入异步代码(例如:ajax定时器),这里使用了定时器作为例子,如果你想表达的是成功回调,你可以在内部调用函数reslove(&#39;一般情况下是后端返回的成功数据)。如果你想表达的是失败回调,你可以调用reject(&#39;一般情况下是后端返回的失败信息&#39;).

这些就是Promise执行的过程!虽然理解着很绕,但是多读几遍绝对有不一样的收获!

Promise链式

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

实际案例:
我想要实现在一个数组中查看一个帖子,但是我最终的目的是得到这个帖子下面的所有评论,这该怎么实现呢?

实现思路
先从一个接口中获取这个帖子的信息,然后通过该帖子的帖子id从而获取到该帖子下的所有评论

代码如下:

pajax({
    url:"http://localhost:3000/news",
    data : {
        author : "james"
    }
}).then(res=>{
    return pajax({
        url : "http://localhost:3000/comments",
        data : {
            newsId : res[0].id
        }
    })
}).then(res=>{
    console.log(res);
}).catch(err=>{
    console.log(err);
})
登入後複製

代码分析:

这里使用了一个Promise已经封装过的ajax,我们从第一个接口中得到了帖子id,然后在then中的函数发送第二个请求(携带了第一个请求返回过来的参数),我们最后想要拿到第二个接口的结果,于是又有了一个then方法,但是在第一个then方法中要把一个新的Promise实例return出去,这样的话,第二个then才起作用!(这是因为then方法是Promise 实例所具有的方法,也就是说,then方法是定义在原型对象Promise.prototype上的)====>我们可以打印一下:console.log(Promise.prototype)

一文帶你輕鬆掌握Promise
可以看的出来原型对象Promise.prototype中是有then方法的!

Promise.all()

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

语法格式:

const p = Promise.all([p1, p2, p3]);
登入後複製

Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会调用Promise.reslove() [该方法可自行了解]自动将参数转为 Promise 实例,再进一步处理。

说那么多白话没用,我们可以根据一个案例,就可以明白Promise.all()的用途了。

实际案例:
如果你想实现一个效果:在一个页面中,等到页面中所有的请求返回数据后,再渲染页面,该怎么实现呢?(在实际开发中我们会看到loading加载页面,等数据返回完后,loading加载页面会消失,整个页面就展现出来了,增强用户的体验。)

实现思路:
通过Promise.all()方法,等多个接口全部接收到数据后,再统一进行处理,然后渲染页面

代码如下:

console.log("显示加载中")
const q1 = pajax({
    url:"http://localhost:3000/looplist"
})

const q2 = pajax({
    url:"http://localhost:3000/datalist"
})
Promise.all([q1,q2]).then(res=>{
    console.log(res)
    console.log("隐藏加载中...")
}).catch(err=>{
    console.log(err)
})
登入後複製

代码分析:

在上方代码中,全局打印显示加载中是代替loading的页面,表示该页面现在正是loading页面中,等到q1q2所请求接口都得到返回的信息后,在then方法中接收收据,并且可以进行渲染页面,同时隐藏了loading加载页面!

小结

不论是在前端的项目开发中还是在前端的面试过程中,Promise的地位就是举足轻重的,虽然解决异步编程的终极解决方案是async和await,但是它们也是基于Promise封装而来的,在以往文章中,我就说过,学习编程重要的是搞懂某个技术是怎么实现的,而不是做一个cv侠,多去思考,才能进步。继续加油吧,少年!

【相关推荐:javascript视频教程编程基础视频

以上是一文帶你輕鬆掌握Promise的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1657
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

言出必行:兌現承諾的好處和壞處 言出必行:兌現承諾的好處和壞處 Feb 18, 2024 pm 08:06 PM

在日常生活中,我們常常會遇到承諾與兌現之間的問題。無論是在個人關係中,或是在商業交易中,承諾的兌現都是建立信任的關鍵。然而,承諾的利與弊也常常會引起爭議。本文將探討承諾的利與弊,並給予一些建議,如何做到言出必行。承諾的利是顯而易見的。首先,承諾可以建立信任。當一個人信守承諾時,他會讓別人相信自己是個可信賴的人。信任是人與人之間建立的紐帶,它可以讓人們更加

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

深入了解Promise.resolve() 深入了解Promise.resolve() Feb 18, 2024 pm 07:13 PM

Promise.resolve()詳解,需要具體程式碼範例Promise是JavaScript中一種用來處理非同步操作的機制。在實際開發中,常常需要處理一些需要依序執行的非同步任務,而Promise.resolve()方法就是用來傳回一個已經Fulfilled狀態的Promise物件。 Promise.resolve()是Promise類別的靜態方法,它接受一個

See all articles