細讀 ES6 | Promise 上篇

配圖源自 Freepik

我認為 Promise 應該算是 ES6 標準最大的亮點,它提供了異步編程的一種解決方案街立。比傳統(tǒng)的回調函數(shù)和事件解決方案滨溉,它更合理、更強大长赞。

一晦攒、簡介

Promise 是一個容器,里面保存著某個未來才會結束的事件(一般為異步操作)的結果得哆。從語法上來說脯颜,Promise 是一個對象,它可以獲取異步操作的消息贩据。

Promise 對象的特點:

  • Promise 對象有且只有三種狀態(tài):pending栋操、fulfilledrejected饱亮,分別表示進行中矾芙、已成功、已失敗近上。

  • 一旦狀態(tài)發(fā)生改變剔宪,就不會再變。狀態(tài)的改變只有兩種可能:pending -> fulfilledpending -> rejected。若發(fā)生了其中一種情況葱绒,狀態(tài)就會一直保存這個結果感帅,這時就成為 resolved(已定型)。

這種以“同步的方式”去表達異步流程地淀,可以避免層層嵌套的回調函數(shù)失球,避免出現(xiàn)“回調地獄”(Callback Hell)。

BTW帮毁,網上有些文章把 fulfilled 狀態(tài)实苞,叫成 resolved,盡管我們可能知道他想表達的意思作箍,但其實是不對的硬梁。

Promise 對象的缺點:

一是無法取消 Promise,一旦創(chuàng)建它就會立即執(zhí)行胞得,無法中途取消荧止;二是若不設置回調函數(shù)情況下,Promise 內部拋出錯誤阶剑,不會反饋到外部跃巡;三是當處于 pending 狀態(tài),無法得知目前進展到哪個階段牧愁。

二素邪、Promise 用法

根據(jù)規(guī)定,Promise 是一個構造函數(shù)猪半,用來生成 Promise 實例對象兔朦。

1. 創(chuàng)建 Promise 對象

示例:

const handler = (resolve, reject) => {
  // some statements...

  // 根據(jù)異步操作的結果,通過 resolve 或 reject 函數(shù)去改變 Promise 對象的狀態(tài)
  if (true) {
    // pending -> fulfilled
    resolve(...)
  } else {
    // pending -> rejected
    reject(...)
  }

  // 需要注意的是:
  // 1. 在上面 Promise 狀態(tài)已經定型(fulfilled 或 rejected)磨确,
  //    因此沽甥,我們再使用 resolve() 或 reject() 或主動/被動拋出錯誤的方式,
  //    試圖再次修改狀態(tài)乏奥,是沒用的摆舟,狀態(tài)不會再發(fā)生改變。
  // 2. 當 Promise 對象的狀態(tài)“已定型”后邓了,若未使用 return 終止代碼往下執(zhí)行恨诱,
  //    后面代碼出現(xiàn)的錯誤(主動拋出或語法錯誤等),在外部都不可見骗炉,無法捕獲到照宝。
  // 3. hander 函數(shù)的返回值是沒意義的。怎么理解痕鳍?
  //    假設內部不包括 resolve() 或 reject() 或內部不出現(xiàn)語法錯誤硫豆,
  //    或不主動拋出錯誤龙巨,僅有類似 `return 'anything'` 語句,
  //    那么 promise 對象永遠都是 pending 狀態(tài)熊响。
}

const promise = new Promise(handler)

Promie 構造函數(shù)接受一個函數(shù)作為參數(shù)旨别,該函數(shù)的兩個參數(shù)分別是 resolvereject。而 resolverejeact 也是函數(shù)汗茄,其作用是改變 Promise 對象的狀態(tài)秸弛,分別是 pending -> fulfilledpending -> rejected

假設構造函數(shù)內不指定 resolvereject 函數(shù)洪碳,那么 Promise 的對象會一直保持著 pending 待定的狀態(tài)递览。

2. Promise 實例

Promise 實例生成以后,當 Promise 內部狀態(tài)發(fā)生變化瞳腌,可以使用 Promise.prototype.then() 方法獲取到绞铃。

const success = res => {
  // 當狀態(tài)從 pending 到 fulfilled 時,執(zhí)行此函數(shù)
  // some statements...
}

const fail = err => {
  // 當狀態(tài)從 pending 到 rejected 時嫂侍,執(zhí)行此函數(shù)
  // some statements...
}

promise.then(success, fail)

then() 方法接受兩個回調函數(shù)作為參數(shù)儿捧,第一個回調函數(shù)在 Promise 對象狀態(tài)變?yōu)?fulfilled 時被調用。第二回調函數(shù)在狀態(tài)變?yōu)?rejected 時被調用挑宠。then() 方法的兩個參數(shù)都是可選的菲盾。

注意,由于 Promise 實例對象的 Promise.prototype.then()各淀、Promise.prototype.catch()懒鉴、Promise.prototype.finally() 方法屬于異步任務中的微任務。注意它們的執(zhí)行時機碎浇,會在當前同步任務執(zhí)行完之后临谱,且在下一次宏任務執(zhí)行之前,被執(zhí)行奴璃。

還有吴裤,Promise 構造函數(shù)(即上述示例的 handler 函數(shù))內部,仍屬于同步任務溺健,而非異步任務。

所以钮蛛,那個經典的面試題就是鞭缭,包括 setTimeoutPromise 等魏颓,然后問輸出順序是什么岭辣?本質就是考察 JavaScript 的事件循環(huán)機制(Event Loop)嘛。這塊內容可以看下文章:JavaScript 事件循環(huán)甸饱。

插了個話題沦童,回來

then() 方法的兩個參數(shù) success()仑濒、fail(),它們接收的實參就是傳遞給 resolve()reject() 的值偷遗。

例如:

function timeout(delay, status = true) {
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      // 一般 reject 應返回一個 Error 實例對象墩瞳,如:new Error('Oops')
      status ? resolve('Success') : reject('Oops')
    })
  }, delay)
  return promise
}

// 創(chuàng)建兩個 Promise 實例對象
const p1 = timeout(1000)
const p2 = timeout(1000, false)

// pending -> fulfilled
p1.then(res => {
  console.log(res) // "Success"
})

// pending -> rejected
p2.then(null, err => {
  console.warn(err) // "Oops"
})

上面示例中,根據(jù) timeout 函數(shù)的邏輯氏豌,p1 實例的 Promise 狀態(tài)會從 pending -> fulfilled喉酌,而 p2 實例則是從 pending -> rejected。因此會分別打印出 "Success"泵喘、"Oops"泪电。

例如,異步加載圖片的例子纪铺。

function loadImage(url) {
  return new Promise((resolve, reject) => {
    const image = new Image()
    image.onload = function () {
      resolve(image)
    }
    image.onerror = function () {
      reject(new Error(`Could not load image at ${url}.`))
    }
    image.src = url
  })
}

loadImage('https://jquery.com/jquery-wp-content/themes/jquery/images/logo-jquery@2x.png')
  .then(
    res => {
      console.log('Image loaded successfully:', res)
    },
    err => {
      console.warn(err)
    }
  )

因此相速,Promise 的用法還是很簡單的,是預期結果的話鲜锚,使用 resolve() 修改狀態(tài)為 fulfilled突诬,非預期結果使用 reject() 修改狀態(tài)為 rejected。具體返回值根據(jù)實際場景返回就好烹棉。

3. Promise 注意事項

在構建 Promise 對象的內部攒霹,使用 resolve()reject() 去改變 Promise 的狀態(tài),并不會終止 resolvereject 后面代碼的執(zhí)行浆洗。

例如:

const promise = new Promise((resolve, reject) => {
  resolve(1)
  // 以下代碼仍會執(zhí)行催束,且會在 then 之前執(zhí)行。
  // reject() 同理伏社。
  console.log(2)
})

promise.then(res => { console.log(res) }) // 先后打印出 2抠刺、1

若要終止后面的執(zhí)行,只要使用 return 關鍵字即可摘昌,類似 return resolve(1)return reject(1)速妖。但如果這樣,其實后面的代碼就沒意義聪黎,因此也就沒必要寫了罕容。千萬別在工作中寫出這樣的代碼,我怕你被打稿饰。這里只是為了說明 resolvereject 不會終止后面的代碼執(zhí)行而已锦秒。

一般來說,調用 resolve()reject() 說明異步操作有了結果喉镰,那么 Promise 的使命就完成了旅择,后續(xù)的操作應該是放到 then() 方法里面,而不是放在 resolve()reject() 后面侣姆。

在前面的示例中生真,resolve()reject() 都是返回一個“普通值”沉噩。如果我們返回一個 Promise 對象,會怎樣呢柱蟀?

首先川蒙,它是允許返回一個 Promise 對象的,但是有些區(qū)別产弹。

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p1 success')
    // reject('p1 fail')
  }, 3000)
})

const p2 = new Promise((resolve, reject) => {
  // 這時返回一個 Promise 對象
  // ?? 注意派歌,這里 resolve(p1) 或 reject(p1) 執(zhí)行的邏輯會有所不同。
  resolve(p1)
  // reject(p1)
})

p2.then(
  res => {
    console.log('p2 then:', res)
  },
  err => {
    console.log('p2 catch:', err)
  }
)

分析如下:

1. 若 p2 內里面 `resolve(p1)` 時:

   當代碼執(zhí)行到 `resolve(p1)` 時痰哨,由于 p1 的狀態(tài)仍是 pending胶果,
   這時 p1 的狀態(tài)會傳遞給 p2扶叉,也就是說 p1 的狀態(tài)決定了 p2 的狀態(tài)厂置,
   因此 `p2.then()` 需要等 p1 的狀態(tài)發(fā)生變化,才會被調用碑韵,
   且 `p2.then()` 獲取到的狀態(tài)就是 p1 的狀態(tài)

   假設代碼執(zhí)行到 `resolve(p1)` 時撬讽,若 p1 的狀態(tài)已定型蕊连,即 fulfilled 或 rejected,
   會立即調用 `p2.then()` 方法游昼。
   PS:這里“立即”是指甘苍,當前同步任務已執(zhí)行完畢的前提下。第 2 點也是如此烘豌。
  
2. 若 p2 內是 `reject(p1)` 時载庭,情況會有所不同:

   當代碼執(zhí)行到 `reject(p1)` 時,由于 p2 的狀態(tài)會變更為 rejected廊佩,
   接著會立即調用 `p2.then()` 方法囚聚,由于是 rejected 狀態(tài),
   因此标锄,會觸發(fā) `p2.then()` 的第二個參數(shù)顽铸,此時 err 的值就是 p1(一個 Promise 對象)。

   假設 p1 的狀態(tài)最終變成了 rejected料皇,那么 err 還要捕獲異常谓松,
   例如 `err.catch(err => { /* do something... */ })`,
   否則的話践剂,在控制臺會報錯毒返,類似:"Uncaught (in promise) p1 fail",
   原因就是 Promise 對象的 rejected 狀態(tài)未處理舷手,導致的。

   假設 p1 的狀態(tài)最終變成 fulfilled劲绪,那么不需要做上一步類似的處理男窟。

上面兩種情況盆赤,其實相當于 Promise.resolve(p1)Promise.reject(p1)歉眷。我們來打印一下兩種結果:

p1 狀態(tài)為 fulfilled 時牺六,p2 狀態(tài)如圖:

p1 狀態(tài)為 rejected 時,p2 狀態(tài)如圖:

三汗捡、Promise.prototype.then()

Promise 的實例具有 then() 方法淑际,它是定義在原型對象 Promise.prototype 上的。當 Promise 實例對象的狀態(tài)發(fā)生變化扇住,此方法就會被觸發(fā)調用春缕。

前面提到 Promise.prototype.then() 接受兩個參數(shù),兩者均可選艘蹋,這里不再贅述锄贼。

then() 方法返回一個新的 Promise 實例對象(注意,不是原來那個 Promise 實例)女阀,也因此可以采用鏈式寫法宅荤,即 then() 方法后面可以再調用另一個 then() 方法。

例如浸策,以下示例使用 Fetch API 進行網絡請求:

window.fetch('/config')
  .then(response => response.json())
  .then(
    res => {
      // do something...
    },
    err => {
      // do something...
    }
  )
  // .then() // ...

以上鏈式調用冯键,會按照順序調用回調函數(shù),后一個 then() 的執(zhí)行庸汗,需等到前一個 Promise 對象的狀態(tài)定型惫确。

四、Promise.prototype.catch()

Promise.prototype.catch() 方法是 then(null, rejection)then(undefined, rejection) 的別名夫晌,用于指定發(fā)生錯誤時的回調函數(shù)雕薪。

同樣地,它會返回一個新的 Promise 實例對象晓淀。

const promise = new Promise((resolve, reject) => {
  reject('Oops') // 或通過 throw 方式主動拋出錯誤所袁,使其變成 rejected 狀態(tài)
  // 但注意的是,前面狀態(tài)“定型”之后凶掰,狀態(tài)是不會再變的燥爷。
  // 這后面試圖改變狀態(tài),或主動拋出錯誤懦窘,或出現(xiàn)其他語法錯誤前翎,
  // 不會被外部捕獲到,即無意義畅涂。
})

promise.catch(err => {
  console.log(err) // "Oops"
})

// 相當于
promise.then(
  null,
  err => {
    console.log(err) // "Oops"
  }
)

通過 throw 等方式使其變成 rejected 狀態(tài)港华,相當于:

const promise = new Promise((resolve, reject) => {
  try {
    throw 'Oops' 
    // 一般地,是拋出一個 Error(或派生)實例對象午衰,如 throw new Error('Oops')
  } catch (e) {
    reject(e)
  }
})

五立宜、捕獲 rejected 狀態(tài)的兩種方式比較

前面提到有兩種方式冒萄,可以捕獲 Promise 對象的 rejected 狀態(tài)。那么孰優(yōu)孰劣呢橙数?

建議如下:

盡量不要在 Promise.prototype.then() 方法里面定義 onRejection 回調函數(shù)(即 then() 的第二個參數(shù))尊流,總使用 Promise.prototype.catch() 方法。

const promise = new Promise((resolve, reject) => {
  // some statements
})

// bad
promise.then(
  res => { /* some statements */ },
  err => { /* some statements */ }
)

// good
promise
  .then(res => { /* some statements */ })
  .catch(err => { /* some statements */ })

上面示例中灯帮,第二種寫法要好于第一種寫法崖技。理由是第二種寫法可以捕獲前面 then() 方法中的異常或錯誤钟哥,也更接近同步寫法(try...catch)迎献。因此,建議總是使用 Promise.prototype.catch() 方法瞪醋。

與傳統(tǒng)的 try...catch 代碼塊不同的是忿晕,即使 Promise 內部出現(xiàn)錯誤,也不會影響 Promise 外部代碼的執(zhí)行银受。

const promise = new Promise((resolve, reject) => {
  say() // 這行會報錯:ReferenceError: say is not defined
})

promise.then(res => { /* some statements */ })

setTimeout(() => {
  console.log(promise) // 這里仍會執(zhí)行践盼,打印出 promise 實例對象
})

上面的示例中,在 Promise 內部就會發(fā)生引用錯誤宾巍,因為 say 函數(shù)并沒有定義咕幻,但并未終止腳本的執(zhí)行。接著還會輸出 promise 對象顶霞。也就是說肄程,Promise 內部的錯誤并不會影響到 Promise 外部代碼,通俗的說法就是“Promise 會吃掉錯誤”选浑。

但是蓝厌,如果腳本放在服務器上執(zhí)行,退出碼就是 0(表示執(zhí)行成功)古徒。不過 Node.js 有一個 unhandledRejection 事件拓提,它專門監(jiān)聽未捕獲的 reject 錯誤,腳本會觸發(fā)這個事件的監(jiān)聽函數(shù)隧膘,可以在監(jiān)聽函數(shù)里面拋出錯誤代态。如下:

注意,Node.js 有計劃在未來廢除 unhandledRejection 事件疹吃。如果 Promise 內部由未捕獲的錯誤蹦疑,會直接終止進程,并且進程的退出碼不為 0萨驶。

catch() 方法中歉摧,也可以拋出錯誤。而且由于 then()catch() 方法均返回一個新的 Promise 實例對象,因此可以采用鏈式寫法叁温,寫出一系列的...

const promise = new Promise((resolve, reject) => {
  reject('Oops')
})

promise
  .then(res => { /* some statements */ })
  .catch(err => { throw new Error('Oh...') })
  .catch(err => { /* 這里可以捕獲上一個 rejected 狀態(tài) */ })
  // ... 還可以寫一系列的 then豆挽、catch 方法

六、Promise.prototype.finally()

在 ES9 標準中券盅,引入了 Promise.prototype.finally() 方法,用于指定 Promise 對象狀態(tài)發(fā)生改變(不管 fulfilled 還是 rejected)后膛檀,都會觸發(fā)此方法锰镀。

const promise = new Promise((resolve, reject) => {
  // some statements
})

promise
  .then(res => { /* some statements */ })
  .catch(err => { /* some statements */ })
  .finally(() => {
    // do something...
    // 注意,finally 不接受任何參數(shù)咖刃,自然也無法得知 Promise 對象的狀態(tài)泳炉。
  })

若 Promise 內部不寫任何 resovle()、或 rejected()嚎杨、或無任何語法錯誤(如上述示例)花鹅,Promise 實例對象的狀態(tài)并不會發(fā)生變化,即一直都是 pending 狀態(tài)枫浙,它都不會觸發(fā) then()刨肃、catch()finally() 方法箩帚。這點就怕有人會誤解真友,狀態(tài)不發(fā)生變化時也會觸發(fā) finally() 方法,這是錯的紧帕。

Promise.prototype.finally() 也是返回一個新的 Promise 實例對象盔然,而且該實例對象的值,就是前面一個 Promise 實例對象的值是嗜。

const p1 = new Promise(resolve => resolve(1))
const p2 = p1.then().finally()
const p3 = p1.then(() => { }).finally()
const p4 = p1.then(() => { return true }).finally()
const p5 = p1.then(() => { throw 'Oops' /* 當然這里沒處理 rejected 狀態(tài) */ }).finally()
const p6 = p1.then(() => { throw 'Oh...' }).catch(err => { return 'abc' }).finally()
const p7 = p1.finally(() => { return 'finally' })
const p8 = p1.finally(() => { throw 'error' })

setTimeout(() => {
  console.log('p1:', p1)
  console.log('p2:', p2)
  console.log('p3:', p3)
  console.log('p4:', p4)
  console.log('p5:', p5)
  console.log('p6:', p6)
  console.log('p7:', p7)
  console.log('p8:', p8)
})

// 解釋一下 `p1` 和 `p1.then()`:
// 當 `then()` 方法中不寫回調函數(shù)時愈案,會發(fā)生值的穿透,
// 即 `p1.then()` 返回的新實例對象(假設為 `x`)的值跟 p1 實例的值是一樣的鹅搪,
// 但注意 `p1` 和 `x` 是兩個不同的 Promise 實例對象站绪。
// 關于值穿透的問題,后面會給出示例涩嚣。

根據(jù)打印結果可以驗證: finally() 方法返回的 Promise 實例對象的值與前一個 Promise 實例對象的值是相等的崇众,但盡管如此,兩者是兩個不同的 Promise 實例對象航厚∏旮瑁可以打印一下 p1 === p7,比較結果為 false幔睬。

關于 Promise.prototype.finally() 的實現(xiàn)眯漩,如下:

Promise.prototype.finally = function (callback) {
  let P = this.constructor
  return this.then(
    value => P.resolve(callback && callback()).then(() => value),
    reason => P.resolve(callback && callback()).then(() => { throw reason })
  )
}

七、總結

關于 Promise.prototype.then()Promise.prototype.catch()赦抖、Promise.prototype.finally() 方法舱卡,總結以下特點:

  • 三者均返回一個全新的 Promise 實例對象。

  • 即使 then()队萤、catch()轮锥、finally() 方法在不指定回調函數(shù)的情況下,仍會返回一個全新的 Promise 實例對象要尔,但此時會出現(xiàn)“值穿透”的情況舍杜,即實例值為前一個實例的值。

  • 假設三者的回調函數(shù)中無語法錯誤(包括不使用 throw 關鍵字) 時赵辕,then()catch() 方法返回的實例對象的值既绩,依靠 return 關鍵字來指定,否則為 undefined还惠。

    finally() 方法稍有不同饲握,即使使用了 return 也是無意義的,因為它返回的 Promise 實例對象的值總是前一個 Promise 實例的值蚕键。

    三個方法的返回操作 return any救欧,相當于 Promise.resolve(any)(這里 any 是指任何值)。

  • then()嚎幸、catch()颜矿、finally() 方法中出現(xiàn)語法錯誤或者利用 throw 關鍵字主動拋出錯誤,它們返回的 Promise 實例對象的狀態(tài)會變成 rejected嫉晶,而且實例對象的值就是所拋出的錯誤原因骑疆。

  • Promise 對象的錯誤具有“冒泡”性質,會一直向后傳遞替废,直到被捕獲為止箍铭。也就是說,錯誤總是會被下一個 catch() 方法捕獲椎镣。

關于值的“穿透”诈火,請看示例:

const person = { name: 'Frankie' } // 使用引用值更能說明問題
const p1 = new Promise(resolve => resolve(person))
const p2 = new Promise((resolve, reject) => reject(person))

// 情況一:fulfilled
p1.then(res => {
  console.log(res === person) // true
})

// 情況二:fulfilled
p1
  .then()
  .then(res => {
    console.log(res === person) // true
  })

// 情況三:rejected
p2
  .catch()
  .then(res => { /* 不會觸發(fā) then */ })
  .catch(err => {
    console.log(err === person) // true
  })

// 情況四:fulfilled
p1
  .finally()
  .then(res => {
    console.log(res === person) // true
  })

從結果上看,盡管三者在不指定回調函數(shù)的情形下状答,“似乎”是不影響結果的冷守。但前面提到 p1p1.then()p1.catch()惊科、p1.finally() 都是兩個不同的 Promise 實例對象拍摇,盡管這些實例對象的值是相等的。

在實際應用場景中馆截,我們應該避免寫出這些“無意義”的代碼充活。但是我們在去學習它們的時候蜂莉,應該要知道。就是“用不用”和“會不會”是兩回事混卵。

下一篇接著介紹 Promise.all()映穗、Promise.race() 等,未完待續(xù)...

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末幕随,一起剝皮案震驚了整個濱河市蚁滋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赘淮,老刑警劉巖枢赔,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拥知,居然都是意外死亡,警方通過查閱死者的電腦和手機碎赢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門低剔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肮塞,你說我怎么就攤上這事襟齿。” “怎么了枕赵?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵猜欺,是天一觀的道長。 經常有香客問我拷窜,道長开皿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任篮昧,我火速辦了婚禮赋荆,結果婚禮上,老公的妹妹穿的比我還像新娘懊昨。我一直安慰自己窄潭,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布酵颁。 她就那樣靜靜地躺著嫉你,像睡著了一般。 火紅的嫁衣襯著肌膚如雪躏惋。 梳的紋絲不亂的頭發(fā)上幽污,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音其掂,去河邊找鬼油挥。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的深寥。 我是一名探鬼主播攘乒,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼惋鹅!你這毒婦竟也來了则酝?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤闰集,失蹤者是張志新(化名)和其女友劉穎沽讹,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體武鲁,經...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡爽雄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沐鼠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挚瘟。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖饲梭,靈堂內的尸體忽然破棺而出乘盖,到底是詐尸還是另有隱情,我是刑警寧澤憔涉,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布订框,位于F島的核電站,受9級特大地震影響兜叨,放射性物質發(fā)生泄漏穿扳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一国旷、第九天 我趴在偏房一處隱蔽的房頂上張望纵揍。 院中可真熱鬧,春花似錦议街、人聲如沸泽谨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吧雹。三九已至,卻和暖如春涂身,著一層夾襖步出監(jiān)牢的瞬間雄卷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工蛤售, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丁鹉,地道東北人妒潭。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像揣钦,于是被迫代替她去往敵國和親雳灾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內容

  • 1. promise要解決的問題: 腦筋急轉彎:把牛關進冰箱里冯凹,要分幾步谎亩? 很顯然,這三個操作不能顛倒順序宇姚,否則任...
    月上秦少閱讀 1,567評論 0 3
  • Promise的含義: ??Promise是異步編程的一種解決方案匈庭,比傳統(tǒng)的解決方案——回調函數(shù)和事件——更合理和...
    呼呼哥閱讀 2,164評論 0 16
  • Promise含義 Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調函數(shù)和事件——更強大浑劳。所謂Pr...
    oWSQo閱讀 1,083評論 0 4
  • Promiese 簡單說就是一個容器阱持,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果,語法上說魔熏,Pr...
    雨飛飛雨閱讀 3,348評論 0 19
  • 1. Promise 的含義 所謂Promise紊选,簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個...
    ROBIN2015閱讀 483評論 0 0