首頁 web前端 js教程 JavaScript中Promise的使用

JavaScript中Promise的使用

May 15, 2018 pm 05:35 PM
promise

Promise是ES6中的函數,規範如何處理非同步任務的回呼函數,功能類似jQuery的defferred。簡單說就是透過promise物件的不同狀態呼叫不同的回呼函數。目前IE8及以下不支援,其他瀏覽器都支援。

promise物件的狀態,從Pending轉換為Resolved或Rejected之後,這個promise物件的狀態就不會再發生任何變化。

使用步驟:

var promise = new Promise(function(resolve, reject) {

 // 异步任务,通过调用resolve(value) 或 reject(error),以改变promise对象的状态;改变状态的方法只能在此调用。

//promise状态改变后,会调用对应的回调方法

});

promise.then(function(value){//resolve时的回调函数,参数由异步的函数传进来})

.catch(function(error){//发生异常时或明确reject()时的回调函数})
登入後複製

 具體使用:

function getURL(URL) {           //因为promise创建时即执行,所以用工厂函数封装promise对象
  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 = "http://httpbin.org/get";
getURL(URL).then(function onFulfilled(value){
  console.log(value);
}).catch(function onRejected(error){
  console.error(error);
})
登入後複製

Promise的回呼只有非同步方式,即使是同步任務的回呼也是非同步執行 。

var promise = new Promise(function (resolve){
  console.log("inner promise");         // 执行1:同步任务先执行
  resolve(‘callBack');
});
promise.then(function(value){
  console.log(value);              // 执行3:虽然注册时状态为resolved,但回调仍是异步的;
});
console.log("outer promise");          // 执行2:同步代码先执行
登入後複製

promise的方法鏈

then方法註冊的回調會依次被調用,每個then方法之間透過return 返回值傳遞參數。但回呼中的異常會導致跳過之間then的回調,直接呼叫catch的回調,之後再繼續呼叫剩下的then的回呼。在then(onFulfilled, onRejected)中,onFulfilled的異常不會被自己的onRejected捕獲,所以優先使用catch。

 promise .then(taskA) .then(taskB) .catch(onRejected) .then(finalTask​​);

 taskA拋異常,taskB被跳過,finalTask​​仍會被調用,因為

 taskA拋異常,taskB被跳過,finalTask​​仍會被調用,因為

 taskA拋異常,taskB被跳過catch回傳的promise物件的狀態為resolved。

then方法內可以返回3種值

1. 返回另一個promise對象,下一個then方法根據其狀態選擇onFullfilled/onRejected回呼函數執行,參數仍由新promise的resolv /reject方法傳遞;

2. 傳回一個同步值,下一個then方法沿用當前promise物件的狀態,無需等非同步任務結束會立即執行;實參為上一then的回傳值;如果沒有return,則預設回傳undefined;

3. 拋出例外(同步/非同步):throw new Error('xxx');

then不僅是註冊一個回呼函數,還會將回調函數的回傳值進行變換,建立並傳回一個新promise物件。實際上Promise在方法鏈中的操作的都不是同一個promise物件。

var aPromise = new Promise(function (resolve) {
  resolve(100);
});
var thenPromise = aPromise.then(function (value) {
  console.log(value);
});
var catchPromise = thenPromise.catch(function (error) {
  console.error(error);
});
console.log(aPromise !== thenPromise); // => true
console.log(thenPromise !== catchPromise);// => true
登入後複製

Promise.all()靜態方法,同時進行多個非同步任務。在接收到的所有promise物件都變成FulFilled 或Rejected 狀態之後才會繼續進行後面的處理。

Promise.all([promiseA, promiseB]).then(function(results){//results是个数组,元素值和前面promises对象对应});

// 由promise对象组成的数组会同时执行,而不是一个一个顺序执行,开始时间基本相同。
function timerPromisefy(delay) {
  console.log('开始时间:”'+Date.now()) 
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve(delay);
    }, delay);
  });
}
var startDate = Date.now();
Promise.all([
  timerPromisefy(100),    //promise用工厂形式包装一下
  timerPromisefy(200),
  timerPromisefy(300),
  timerPromisefy(400)
]).then(function (values) {
  console.log(values);  // [100,200,300,400]
});
登入後複製

不同時執行,而是一個接著一個執行promise

//promise factories返回promise对象,只有当前异步任务结束时才执行下一个then
function sequentialize(promiseFactories) {
  var chain = Promise.resolve();
  promiseFactories.forEach(function (promiseFactory) {
    chain = chain.then(promiseFactory);
  });
  return chain;
}
登入後複製

Promise.race()同all()類似,但是race()只要有一個promise物件進入FulFilled 或Rejected 狀態的話,就會執行對應的回呼函數。不過在第一個promise物件變成Fulfilled之後,並不影響其他promise物件的繼續執行。

//沿用Promise.all()的例子
Promise.race([
  timerPromisefy(1),
  timerPromisefy(32),
  timerPromisefy(64),
  timerPromisefy(128)
]).then(function (value) {
  console.log(values);  // [1]
});
登入後複製

Promise.race()作為計時器的妙用

Promise.race([
  new Promise(function (resolve, reject) {
    setTimeout(reject, 5000);     // timeout after 5 secs
  }),
  doSomethingThatMayTakeAwhile()
]);
登入後複製

在then改變promise狀態

因為then的回呼中只有value參數,沒有改變狀態的方法(只能在構造方法的非同步任務中使用),要改變傳給下一個then的promise對象的狀態,只能重新new一個新的Promise對象,在非同步任務中判斷是否改變狀態,最後return出去傳給下一個then/catch。

var promise = Promise.resolve(‘xxx');//创建promise对象的简介方法
promise.then(function (value) {
  var pms=new Promise(function(resolve,reject){
    setTimeout(function () {
      // 在此可以判断是否改变状态reject/resolve
      Reject(‘args');
    }, 1000);
  })
  return pms;  //该promise对象可以具有新状态,下一个then/catch需要等异步结束才会执行回调;如果返回普通值/undefined,之后的then/catch会立即执行
}).catch(function (error) {
  // 被reject时调用
  console.log(error)
});
登入後複製

取得兩個promises的結果

//方法1:通过在外层的变量传递
var user;
getUserByName('nolan').then(function (result) {
  user = result;
  return getUserAccountById(user.id);
}).then(function (userAccount) {
  //可以访问user和userAccount
});

//方法2:后一个then方法提到前一个回调中
getUserByName('nolan').then(function (user) {
  return getUserAccountById(user.id).then(function (userAccount) {
    //可以访问user和userAccount
  });
});
登入後複製

注意使用promise時的整體結構

假定doSomething()和doSomethingElse()都回傳了promise物件

#常用方式:

doSomething().then(doSomethingElse).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(resultOfDoSomething)  //返回新promise,下一个then要收到新状态才执行
         |------------------|
                   finalHandler(resultOfDoSomethingElse)
                   |---------------------|
登入後複製

常用變通方式:

doSomething().then(function () { return doSomethingElse();}).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(undefined) //then外层函数的arguments[0]== resultOfDoSomething
         |------------------|
                   finalHandler(resultOfDoSomethingElse)
                   |------------------|
登入後複製

錯誤方式1:

doSomething().then(function () { doSomethingElse();}).then(finalHandler);
doSomething
|-----------------|
         doSomethingElse(undefined)  //虽然doSomethingElse会返回promise对象,但最外层的回调函数是return undefined,所以下一个then方法无需等待新promise的状态,会马上执行回调。
         |------------------|
         finalHandler(undefined)
         |------------------|
登入後複製

錯誤方式2:

doSomething().then(doSomethingElse()).then(finalHandler);
doSomething
|-----------------|
doSomethingElse(undefined)     //回调函数在注册时就直接被调用
|----------|
         finalHandler(resultOfDoSomething)
         |------------------|
登入後複製
###更多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

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++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教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1272
29
C# 教程
1252
24
言出必行:兌現承諾的好處和壞處 言出必行:兌現承諾的好處和壞處 Feb 18, 2024 pm 08:06 PM

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

在Vue應用中遇到Uncaught (in promise) TypeError怎麼辦? 在Vue應用中遇到Uncaught (in promise) TypeError怎麼辦? Jun 25, 2023 pm 06:39 PM

Vue是一款受歡迎的前端框架,在開發應用時經常會遇到各種各樣的錯誤和問題。其中,Uncaught(inpromise)TypeError是常見的一種錯誤型別。在本篇文章中,我們將探討它的產生原因和解決方法。什麼是Uncaught(inpromise)TypeError? Uncaught(inpromise)TypeError錯誤通常出現在

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

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

哪些瀏覽器支援Promise? 哪些瀏覽器支援Promise? Feb 19, 2024 pm 04:41 PM

瀏覽器相容性:哪些瀏覽器能夠支援Promise?隨著Web應用程式的複雜性不斷提高,開發人員迫切需要解決JavaScript中的非同步程式設計問題。過去,開發人員通常使用回調函數來處理非同步操作,但這會導致程式碼複雜且難以維護。為了解決這個問題,ECMAScript6引入了Promise,它提供了一種更直觀、更靈活的處理非同步操作的方式。 Promise是一種用於處理異

實例解析ES6 Promise的原理與使用 實例解析ES6 Promise的原理與使用 Aug 09, 2022 pm 03:49 PM

利用Promise對象,把普通函數改成返回Promise的形式,解決回調地獄的問題。明白Promise的成功失敗呼叫邏輯,可以靈活的進行調整。理解核心知識,先用起來,慢慢整合吸收知識。

promise物件有哪些 promise物件有哪些 Nov 01, 2023 am 10:05 AM

promise物件狀態有:1、pending:初始狀態,既不是成功,也不是失敗狀態;2、fulfilled:意味著操作成功完成;3、rejected:意味著操作失敗。一個Promise物件一旦完成,就會從pending狀態變成fulfilled或rejected狀態,且不能再改變。 Promise物件在JavaScript中被廣泛使用,以處理如AJAX請求、定時操作等非同步操作。

promise什麼意思 promise什麼意思 Nov 02, 2023 pm 05:30 PM

Promise是一種用於處理非同步操作的程式設計模式,它是一種代表了非同步操作最終完成或失敗的對象,可以看作是對非同步操作的一種承諾,它可以更好地管理和組織非同步程式碼,使得程式碼更可讀性高、可維護性強。 Promise物件有三個狀態:pending、fulfilled和rejected。 Promise的核心思想是將非同步操作從回調函數中分離出來,透過鍊式呼叫的方式來表達非同步操作之間的依賴關係。

PHP 函數回傳 Promise 物件有什麼優勢? PHP 函數回傳 Promise 物件有什麼優勢? Apr 19, 2024 pm 05:03 PM

優點:非同步和非阻塞,不阻塞主執行緒;提高程式碼可讀性和可維護性;內建錯誤處理機制。

See all articles