JavaScript非同步編程Promise模式的6個特性_javascript技巧

來源:互聯網
上載者:User

在我們開始正式介紹之前,我們想看看Javascript Promise的樣子:

複製代碼 代碼如下:

var p = new Promise(function(resolve, reject) {
  resolve("hello world");
});

p.then(function(str) {
  alert(str);
});

1. then()返回一個Forked Promise

以下兩段代碼有什麼區別呢?

複製代碼 代碼如下:

// Exhibit A
var p = new Promise(/*...*/);
p.then(func1);
p.then(func2);

// Exhibit B
var p = new Promise(/*...*/);
p.then(func1)
.then(func2);

如果你認真以上兩段代碼等同的話,那麼Promises只不過是一個一維的回呼函數數組。然而,其實不是這樣的。每一個then()調用都返回一個forked promise。因此,ExhibitA中,如果func1()拋出一個異常,func2()仍舊正常調用。

在ExhibitB中,如果func1()拋出一個錯誤,fun2()將不會被調用,因為第一個調用返回了一個新的promise,這個在func1()中會被拒絕。結果是func2()被跳過。

總結:promises可以被fork成多個路徑,類似複雜的流程圖。

2. Callback應該傳遞結果

當你運行下面代碼的時候什麼會得到警告提示呢?

複製代碼 代碼如下:

var p = new Promise(function(resolve, reject) {
  resolve("hello world");
});

p.then(function(str) {})
.then(function(str) {
  alert(str);
});

第二個then()中的alert沒有顯示任何內容。這是因為回呼函數,在promise的上下文中,因為結果的變化並沒有回呼函數。promise期望你的回呼函數返回同樣的結果或者返回一個替換結果,然後被傳遞到下一個回呼函數中。

類似使用adpater來變化結果,如下:

複製代碼 代碼如下:

var feetToMetres = function(ft) { return ft*12*0.0254 };

var p = new Promise(/*...*/);

p.then(feetToMetres)
.then(function(metres) {
  alert(metres);
});

3. 只有來自上一層的異常可以被捕捉

這兩段代碼有什麼區別?

複製代碼 代碼如下:

// Exhibit A
new Promise(function(resolve, reject) {
  resolve("hello world");
})
.then(
  function(str) {
    throw new Error("uh oh");
  },
  undefined
)
.then(
  undefined,
  function(error) {
    alert(error);
  }
);
 

// Exhibit B
new Promise(function(resolve, reject) {
  resolve("hello world");
})
.then(
  function(str) {
    throw new Error("uh oh");
  },
  function(error) {
    alert(error);
  }
);


在第一段代碼中,在第一個then()中的異常被拋出,將會被第二個then()捕捉,然後“uh oh”警告將會被觸發。這個遵循只有前一個層次的異常會被捕捉。

在第二段代碼中,回呼函數和錯誤回呼函數是同一個層次,意味著當異常在回調中拋出,將不會被捕捉。事實上,第二段代碼的錯誤回調將只會在promise為拒絕狀態或者promise本身出錯的情況下拋出

4. 錯誤可以被恢複

在一個錯誤回呼函數中,如果你不重新拋出錯誤,promise會假設你已經從錯誤中恢複,並且反轉成為已解決狀態。在下一個例子中,"i'm saved" 將會被顯示,這是因為在第一個then()中的錯誤回調沒有重新拋出異常。

複製代碼 代碼如下:

var p = new Promise(function(resolve, reject) {
  reject(new Error("pebkac"));
});

p.then(
  undefined,
  function(error) { }
)
.then(
  function(str) {
    alert("I am saved!");
  },
  function(error) {
    alert("Bad computer!");
  }
);

Promise可以被看作洋蔥上的層次。每一個then()添加另外一個層次到洋蔥上。每一個層次代表了一個被處理的活動。當層次結束,結果被認為已經修複並且為下一個層次做好了準備。

5. Promises可以被暫停

因為你已經準備好了在一個then()方法中執行,並不意味著你不能夠暫停並且提前運行其他。 為了暫停目前的promise,或者讓它等待以便另外一個promise完成,簡單在then()中返回另外一個promise。

複製代碼 代碼如下:

var p = new Promise(/*...*/);

p.then(function(str) {
  if(!loggedIn) {
    return new Promise(/*...*/);
  }
})
.then(function(str) {
  alert("Done.");
})

在前面代碼中,直到新的promise解析後提示才會出現。這是一個方便的方式在已存在的非同步代碼路徑中來引入更多地依賴。例如,你可能發現使用者session已經timeout,並且你可能希望在繼續前面的代碼路徑前初始化第二個登陸。

6. Resolved Promises並不會立刻執行

運行下面代碼會得到提示框嗎?

複製代碼 代碼如下:

function runme() {
  var i = 0;

  new Promise(function(resolve) {
    resolve();
  })
  .then(function() {
    i += 2;
  });
  alert(i);
}

因為promise被立刻解析,然後then()方法被立刻執行,所以你可能會認為會探出提示2。但是promise定義要求所有的調用都被強制非同步。因此提示會在被修改前產生。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.