Promise 對象

Promise 是異步編程的一種解決方案场航,比傳統(tǒng)的解決方案 —— 回調(diào)函數(shù)和事件 —— 更合理且強大

Promise尖啡,簡單來說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果竭业。從語法上來說,Promise 是一個對象悦冀,從它可以獲取異步操作的消息。

Promise 對象有以下兩個特點:

  1. 對象的狀態(tài)不受外界影響睛琳。Promise對象代表一個異步操作盒蟆,有 3 中狀態(tài)

    • Pending(進行中)
    • Fulfilled(已成功)
    • Rejected(已失敗)
      只有異步操作的結果可以決定當前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)师骗。(這也是 "promise" 這個名字的由來历等,它在英語中意思是“承諾”,表示其它手段無法改變)
  2. 一旦狀態(tài)改變就不會再變丧凤,任何時候都可以得到這個結果募闲。Promise 對象的狀態(tài)改變只有兩種可能:

    • 從 Pending 變?yōu)?Fulfilled
    • 從 Pending 變?yōu)?Rejected
      只要這兩種情況發(fā)生步脓,狀態(tài)就凝固了愿待,不會再變,而是一直保持這個結果靴患,這時就稱為 Resolved(已定性)

Promise 也有一些缺點:

  1. 無法取消 Promise仍侥,一旦新建它就會立即執(zhí)行,無法中途取消
  2. 如果不設置回調(diào)函數(shù)鸳君,Promise 內(nèi)部拋出錯誤不會反應到外部
  3. 當處于 Pending 狀態(tài)時农渊,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)

如果某些事件不斷地反復發(fā)生,一般來說或颊,使用 Stream 模式(nodejs.org/api/stream.html)

二砸紊、基本用法

ES6 規(guī)定,Promise 對象是一個構造函數(shù)囱挑,用來生成 Promise 實例醉顽。

創(chuàng)建一個Promise 實例

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操作成功 */) {
    resolve()
  } else {
    // 操作失敗
    reject()
  }
})

Promise 構造函數(shù)接受一個函數(shù)作為參數(shù),該函數(shù)的兩個參數(shù)分別是:

  • resolve:將 Promise 對象的狀態(tài)從 “未完成” 變成 “成功”(即從 Pending 變?yōu)?Resolved)平挑,并將異步操作的結果作為參數(shù)傳遞出去
  • reject:將Promise 對象的狀態(tài)從 “未完成” 變?yōu)?“失敗” (即從 Pending 變?yōu)?Rejected)游添,并將異步操作報出的錯誤作為參數(shù)傳遞出去

Promise 實例生成以后系草,可以用 then 方法分別制定 Resolved 狀態(tài) 和 Rejected 狀態(tài)的回調(diào)函數(shù)。

promise.then(function(value) {
  // resolve
}, function(error) {
  // reject
})

第一個回調(diào)函數(shù)是 Promise 對象的狀態(tài)變?yōu)?Resolved 時調(diào)用唆涝,第二個回調(diào)函數(shù)是 Promise 對象的狀態(tài)變?yōu)?Rejected 調(diào)用找都。

下面是一個 Promise 對象的簡單例子。

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done')
  })
}

timeout(100).then((value) => {
  console.log(value)
})

Promise 新建后就會立即執(zhí)行

let promise = new Promise(function(resolve, reject) {
  console.log('Promise')
  resolve()
})

promise.then(function() {
  console.log('Resolved.')
})

console.log('Hi!')

// Promise
// Hi
// Resolved

下面是異步加載圖片的例子

function loadImageAsync(url) {
  return new Promise((resolve, reject) => {
    var image = new Image()

    image.onload = function() {
      resolve(image)
    }

    image.onerror = function() {
      reject(new Error('Could not load image at' + url))
    }

    image.src = url
  })
}

用 Promise 對象實現(xiàn) AJAX 操作

var getJSON = function(url) {
  var promise = new Promise((resolve, reject) => {
    var client = new XMLHttpRequest()
    client.open('GET', url)
    client.onreadystatechange = handler
    client.responseType = 'json'
    client.setRequestHeader("Accept", "application/json")
    client.send()

    function handler() {
      if (this.readyState !== 4) {
        return
      }
      if (this.status === 200) {
        resolve(this.response)
      } else {
        reject(new Error(this.statusText))
      }
    }
  })
  return promise
}

getJSON("/posts.json").then(json => {
  console.log('Contents:' + json)
}, error => {
  console.error('出錯了'廊酣,error)
})

如果調(diào)用 resolve 函數(shù) 和 reject 函數(shù)時帶有參數(shù)能耻,那么這些參會會被傳遞給回調(diào)函數(shù) reject 函數(shù)的參數(shù)通常是 Error 對象的實例,表示拋出的錯誤亡驰,resolve 函數(shù)的參數(shù)處理正常的值外嚎京,還可能是另外一個 Promise 實例。

var p1 = new Promise((resolve, reject) => {
  // ...
})

var p2 = new Promise((resolve, reject) => {
  // ...
  resolve(p1)
})

p2 的 resolve方法將 p1 作為參數(shù)隐解,即一個異步操作的結果是返回另一個異步操作

此時 p1 的狀態(tài)就會傳遞給p2鞍帝。也就是說,p1的狀態(tài)決定了 p2 的狀態(tài)煞茫。如果 p1 的狀態(tài)時 pending帕涌,那么 p2 的回調(diào)函數(shù)就會等待 p1 的狀態(tài)改變;如果 p1 的狀態(tài)已經(jīng)是 Resolved 或 Rejected续徽,那么 p2 的回調(diào)函數(shù)將會立即執(zhí)行

var p1 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('fail')), 3000)
})

var p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve(p1), 1000)
})

p2
  .then(result => console.log(result))
  .catch(error => console.log(error))

上面的代碼中蚓曼,p1 是一個 Promise,3秒之后變成了 rejected钦扭。p2 的狀態(tài)在 1 秒之后改變纫版,resolve 方法返回的是 p1,。由于 p2 返回的是另一個 Promise客情,導致 p2 的狀態(tài)無效其弊,由 p1 的狀態(tài)決定 p2 的狀態(tài)。所以膀斋,后面的 then 語句都變成針對后者(p1)的梭伐。再過2秒,p1 變成 Rejected仰担,觸發(fā) catch 方法指定的回調(diào)函數(shù)


注意糊识,調(diào)用 resolve 或 reject 并不會終止 Promise 的參數(shù)函數(shù)的執(zhí)行

new Promise((resolve, reject) => {
  resolve(1)
  console.log(2)
}).then(r => {
  console.log(r)
})

// 2
// 1

因為 立即 resolve 的 Promise 是在本輪事件循環(huán)的末尾執(zhí)行,總是晚于本輪循環(huán)的同步任務

一般來說摔蓝,調(diào)用 resolve 或 reject 之后赂苗,Promise 的使命就完成了。所以贮尉,最好在他們前面加上 return 語句拌滋,這樣就不會產(chǎn)生意外了。

new Promise((resolve, reject) => {
  return resolve(1)
  // 后面的語句不會執(zhí)行
  console.log(2)
})

三绘盟、Promise.prototype.then()

Promise 實例具有 then 方法鸠真,即 then 方法是定義在原型對象 Promise.prototype 上的悯仙。它的作用是為 Promise 實例添加狀態(tài)改變時的回調(diào)函數(shù)否灾。
第一個參數(shù)是 Resolved 狀態(tài)的回調(diào)函數(shù)
第二個參數(shù)(可選) 是 Rejected 狀態(tài)的回調(diào)函數(shù)

then 方法返回的是一個新的 Promise 實例(注意嗽仪,不是原來那個 Promise 實例)。因此可以采用鏈式寫法来破,即 then 方法后面再調(diào)用另一個 then 方法祭隔。

getJSON("/posts.json").then(function(json) {
  return json.post
}).then(function(post) {
  // ...
})

采用鏈式的 then 可以指定一組按照次序調(diào)用的回調(diào)函數(shù)货岭。這時,前一個回調(diào)函數(shù)有可能返回的還是一個 Promise 對象(即有異步操作)疾渴,而后一個回調(diào)函數(shù)就會等待該 Promise 對象的狀態(tài)發(fā)生變化千贯,再次調(diào)用

getJSON('/post/1.json').then(
  post => getJSON(post.commentURL)
).then(
  comments => console.log('Resolved:', comments),
  err => console.log('Rejected:', err)
)

四、Promise.prototype.catch()

Promise.prototype.catch 方法是 .then(null, rejection) 的別名搞坝,用于指定發(fā)生錯誤時的回調(diào)函數(shù)搔谴。

getJSON('/posts.json').then(posts => {
  // ...
}).catch(error => {
  // 處理 getJSON 和前一個回調(diào)函數(shù)運行時發(fā)生的錯誤
  console.log('err', error)
})

此外,then 方法指定的回調(diào)函數(shù)如果在運行中拋出錯誤桩撮,也會被 catch 方法捕獲

Promise 爬出一個錯誤也會被 catch 方法指定的回調(diào)函數(shù)所捕獲

var promise = new Promise((resolve, reject) => {
  throw new Error('test')
})

promise.catch(error => {
  console.log(error)
})
// Error: test

/* 上面的寫法等同于下面的兩種寫法 */
// 寫法一
var promise = new Promise((resolve, reject) => {
  try {
    throw new Error('test')
  } catch(e) {
    reject(e)
  }
})

promise.catch(error => {
  console.log(error)
})


// 寫法二
var promise = new Promise((resolve, reject) => {
  reject(new Error('test'))
})

promise.catch(error => {
  console.log(error)
})

如果 Promise 狀態(tài)已經(jīng)變成 Resolved敦第,再拋出錯誤是無效的

var promise = new Promise((resolve, reject) => {
  resolve('ok')
  throw new Error('test')
})
promise
  .then(value => { console.log(value) })
  .catch(error => { console.log(error) })

// ok

因為 Promise 的狀態(tài)一旦改變,就會永久保存該狀態(tài)店量,不會再改變

Promise 對象的錯誤具有"冒泡"性質(zhì)芜果,會一直向后傳遞,直到被捕獲為止融师。也就是說右钾,錯誤總是會被下一個 catch 語句捕獲。

getJSON('/post/1.json')
  .then(post => getJSON(post.commentURL))
  .then(comments => {  /*some code */  })
  .catch(error => {
    // 處理前面 3 個Promise 產(chǎn)生的錯誤
   })

上面的代碼中旱爆,一共3個 Promise 對象:一個由 getJSON 產(chǎn)生舀射,兩個 由 then 產(chǎn)生。其中任何一個拋出的錯誤都會被最后一個 catch 捕獲疼鸟。

一般來說后控,不要再 then 方法中定義 Rejected 狀態(tài)的回調(diào)函數(shù) (即 then 的第二個參數(shù)),而應總是使用 catch 方法

如果沒有使用 catch 方法指定錯誤處理的回調(diào)函數(shù)空镜,Promise 對象拋出的錯誤不會傳遞到外層代碼,即不會有任何反應

var someAsyncThing = function() {
  return new Promise((resolve, reject) => {
    // 下面一行會報錯捌朴,因為 x 沒有聲明
    resolve(x + 2)
  })
}

someAsyncThing()
  .then(() => {
    console.log('everything is great')
  })

瀏覽器此時會打印出錯誤 “ReferenceError:x is not defined”吴攒,不過不會總之腳本執(zhí)行

需要注意的是,catch 方法返回的還是一個 Promise 對象砂蔽,因此后面還可以調(diào)用 then 方法洼怔。

var someAsyncThing = function() {
  return new Promise((resolbe, reject) => {
    // 下面一行會報錯,因為 x 沒有聲明
    resolve(x + 2)
  })
}

someAsyncThing()
  .catch(error => {
    console.log('oh on', error)
  })
  .then(() => {
    console.log('carry on')
  })
// oh on ReferenceError: resolve is not defined
// carry on

如果沒有報錯左驾,則會跳過 catch 方法

Promise.resolve()
  .catch(error => {
    console.log('oh on', error)
  })
  .then(() => {
    console.log('carry on')
  })
// carry on

如果上面代碼中镣隶,then 方法里面報錯极谊,就與前面的 catch 無關了

catch 中還能再拋出錯誤,如果后面沒有別的 catch 方法安岂,導致這個錯誤不會被捕獲轻猖,也不會傳遞到外層。

someAsyncThing()
  .then(() => someOtherAsyncThing())
  .catch(error => {
    console.log('oh on', error)
    // 下面操作會報錯域那,因為 y 沒有聲明
    y + 2
  })
  .catch(error => {
    console.log('carry on', error)
  })

// oh no [ReferenceError: x is not defined]
// carry on [ReferenceError:y is not defined]

五咙边、Promise.all()

Promise.all 方法用于將多個 Promise 實例 包裝成一個新的 Promise 實例

var p = Promise.all([p1, p2, p3])

Promise.all 方法接受一個數(shù)組作為參數(shù),p1次员、p2败许、p3 都是 Promise 對象的實例(Promise.all 方法的參數(shù)不一定是數(shù)組,但是必須具有 Iterator 接口淑蔚,且返回的每個成員都是 Promise 實例)

p 的狀態(tài) 由 p1市殷、p2、p3決定刹衫,分成兩種情況:

  • 只有 p1被丧、p2、p3 的狀態(tài)都變成 Fulfilled绪妹,p 的狀態(tài)才會變成 Fulfilled甥桂,此時 p1、p2邮旷、p3的返回值組成一個數(shù)組黄选,傳遞給 P 的回調(diào)函數(shù)。
  • 只要 p1婶肩、p2办陷、p3 中有一個被 Rejected,p 的狀態(tài)就變成Rejected律歼,此時第一個被 Rejected 的實例的返回值會傳遞給 p 的回調(diào)函數(shù)
// 生成一個 Promise 對象的數(shù)組
var promise = [2, 3,  5, 7, 1,, 13].map(id => {
  return getJSON('/post/' + id + '.json')
})

Promise.all(promise).then(posts => {
  // ...
}).catch(reason => {
  // ...
})

如上民镜,即是 包含6個 Promise 實例的數(shù)組

下面是另一個例子

const databasePromise = connectDatabase()

const booksPromise = databasePromise
  .then(findAllBooks)

const userPromise = databasePromise
  .then(getCurrentUser)

Promise.all([
  booksPromise,
  userPromise
])
  .then(([books, user]) => pickTopRecommentations(books, user))

booksPromise 和 userPromise 是兩個異步操作,只有他們的結果都返回险毁,才會觸發(fā) PickTopRecmmentations 回調(diào)函數(shù)

如果作為參數(shù)的 Promise 實例自身定義了 catch 方法制圈,那么 它被 rejected 是并不會觸發(fā) Promise.all() 的 catch 方法

const p1 = new Promise((resolve, reject) => {
  resolve('hello')
})
  .then(result => result)
  .catch(e => e)

const p2 = new Promise((resolve, reject) => {
  throw new Error('報錯了')
})
.then(result => result)
.catch(e => e)

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e))
// ["hello", Error: 報錯了]

上面代碼中,p2 首先會 rejected畔况,但是 p2 有自己的 catch 方法鲸鹦,該方法返回的是一個新的 Promise 實例,p2 實際上指向的是這個實例跷跪。該實例執(zhí)行完 catch 方法后也會變成 resolved馋嗜,導致 Promise.all() 方法參數(shù)里面的兩個實例都會 resolved,因此會調(diào)用 then 方法指定的回調(diào)函數(shù)吵瞻,而不會調(diào)用 catch 方法指定的回調(diào)函數(shù)葛菇。

如果 p2 沒有自己的 catch 方法甘磨,就會調(diào)用 Promise.all() 的 catch 方法

六、Promise.race()

Promise.race 方法同樣是將多個 Promise 實例包裝成一個新的 Promise 實例眯停。Promise.race 方法的參數(shù)與 Promise.all 方法一樣

var p = Promise.race([p1, p2, p3)

只要 p1济舆、p2庵朝、p3 中有一個實例率先改變狀態(tài)吗冤,p 的狀態(tài)就跟著改變九府。那個率先改變的 Promise 實例的返回值就傳遞給 P 的回調(diào)函數(shù)

const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
])

p.then(response => console.log(response))
p.catch(error => console.log(error))

上面的代碼中,如果 5秒之內(nèi) fetch 方法無法返回結果侄旬,變量 p 的狀態(tài)就會變?yōu)?Rejected肺蔚,從而觸發(fā) catch 方法指定的回調(diào)函數(shù)

七、Promise.resolve()

有時候需要將現(xiàn)有對象轉(zhuǎn)為 Promise 對象宣羊,Promise.resolve 方法就起到這個作用

var jsPromise = Promise.resolve($.ajax('/whatever.json'))

Promise.resolve 等價于下面的寫法

Promise.resolve('foo')
// 等價于
new Promise( resolve => resolve('foo'))

Promise.resolve 方法的參數(shù)分成以下4種情況:

1. 參數(shù)是一個 Promise 實例
如果參數(shù)是 Promise 實例,那么 Promise.resolve 將不做任何修改仇冯,原封不動地返回這個實例

2. 參數(shù)是一個 thenable 對象
thenable 對象值的是具體 then 方法的對象,比如下面這個對象

let thenable = {
  then(resolve, reject) {
    resolve(42)
  }
}

Promise.resolve 方法會將這個對象轉(zhuǎn)為 Promise 對象族操,然后立即執(zhí)行 thenable 對象的 then 方法苛坚。

let thenable = {
  then(resolve, reject) {
    resolve(42)
  }
}

let p1 = Promise.resolve(thenable)
p1.then(value => {
  console.log(value) // 42
})

thenable 對象 then 方法執(zhí)行后,對象 p1 的狀態(tài)就變?yōu)?resolved 從而立即執(zhí)行最后的 then 方法指定的回調(diào)函數(shù)泼舱,輸出 42。

3. 參數(shù)不是具有 then 方法的對象或根本不是對象
如果參數(shù)是一個原始值娇昙,或者是一個不具有 then 方法的對象笤妙,那么 Promise.resolve 方法返回一個新的 Promise 對象冒掌,狀態(tài)為 Resolved

var p = Promise.resolve('Hello')

p.then(s => {
  console.log(s)
})
// Hello

上面生成了一個新的 Promise 對象的實例p。由于字符串 Hello 不屬于異步操作(判斷方法是 字符串對象 不具有 then 方法)宋渔,返回 Promise 實例的狀態(tài)從生成起就是 Resolved,所以回調(diào)函數(shù)會立即執(zhí)行。Promise.resolve 方法的參數(shù)會同時傳給回調(diào)函數(shù)严蓖。
4. 不帶有任何參數(shù)
Promise.resolve 方法允許在調(diào)用時不帶有參數(shù)氧急,而直接返回一個 Resolved 狀態(tài)的 Promise 對象毫深。

var p = Promise.resolve()

p.then(() => {
  // ....
})

需要注意的是,立即 resolve 的 Promise 對象是在本輪“事件循環(huán)”(event loop) 結束時哑蔫,而不是在下一輪“事件循環(huán)”開始時。

setTimeout(() => {
  console.log('three')
}, 0)

Promise.resolve().then(() => {
  console.log('two')
})

console.log('one')

上面的代碼中闸迷,setTimeout(fn, 0) 是在下一輪“事件循環(huán)” 開始時執(zhí)行的,Promise.resolve() 在本輪“事件循環(huán)”結束時執(zhí)行逮走,console.log('one')則是立即執(zhí)行

八今阳、Promise.reject()

Promise.reject(reason) 方法也會返回一個新的 Promise 實例师溅,狀態(tài)為 Rejected

var p = Promise.reject('出錯了')
// 等同于
var p = new Promise((resolve, reject) => reject('出錯了'))

p.then(null, s => {
  console.log(s)
})
// 出錯了

Promise.reject() 方法的參數(shù)會原封不動地作為 reject 的理由變成后續(xù)方法的參數(shù)盾舌。這一點與 Promise.resolve() 方法不一致。

const thenable = {
  then(resolve, reject) {
    reject('出錯了')
  }
}

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true

上面的代碼中窿锉,Promise.reject 方法的參數(shù)是一個 thenable 對象窖维,執(zhí)行以后榆综,后面 catch 方法的參數(shù)不是 reject 拋出的 “出錯了” 這個字符串铸史,而是 thenable 對象

九、兩個有用的附加方法

ES6 的 Promise API 提供的方法不是很多琳轿,可以自己部署一些有用的方法。下面部署兩個不在 ES6 中但很有用的方法崭篡。

9.1、done()

無論 Promise 對象的回調(diào)鏈以 then 方法還是 catch 方法結尾迹炼,只要最后一個方法拋出錯誤,都有可能無法捕捉到(因為 Promise 內(nèi)部的錯誤不會冒泡到全局)斯入。為此,我們可以提供一個 done 方法刻两,它總是處于回調(diào)鏈的尾端,保證拋出任何可能出現(xiàn)的錯誤磅摹。

asyncFunc()
  .then(f1)
  .catch(r1)
  .then(f2)
  .done()

它的實現(xiàn)代碼相當簡單

Promise.prototype.done = function(onFulfilled, onRejected) {
  this.then(onFulfilled, onRejected)
    .catch(reason => {
      // 拋出一個全局錯誤
      setTimeout(() => { throw reason }, 0)
    })
}

done 方法可以像 then 方法那樣使用,提供 Fulfilled 和 Rejected 狀態(tài)的回調(diào)函數(shù)饼灿,也可以不停任何參數(shù)。但不管怎么樣赔退,done 方法都會捕捉到 任何可能出現(xiàn)的錯誤证舟,并向全局拋出

9.2硕旗、finally()

finally 方法用于指定不管 Promise 對象最后狀態(tài)如何都會執(zhí)行的操作女责。它與 done 方法的最大區(qū)別在于,他接受一個普通的回調(diào)函數(shù)作為參數(shù)抵知,該函數(shù)不管怎樣都必須執(zhí)行。

server.listen(0)
  .then(() => {
    // run test
  })
  .finally(server.stop)

上面的例子刷喜,服務器使用 Promise 處理請求,然后使用 finally 方法關掉服務器

它的實現(xiàn)也很簡單

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

不管前面的 Promise 是 fulfilled 還是 rejected初茶,都會執(zhí)行回調(diào)函數(shù) callback

十浊闪、應用

10.1恼布、加載圖片

const prelpadImage = function(path) {
  return new Promise(function (resolve, reject) {
    var image = new Image()
    image.onload = resolve
    image.onerror = reject
    image.src = path
  })
}

10.2 Generator 函數(shù)與 Promise 的結合

使用 Generator 函數(shù)管理流程,遇到異步操作時通常返回一個 Promise 對象

function getFoo() {
  return new Promise(function (resolve, reject) {
    resolve('foo')
  })
}

var g = function* () {
  try {
    var foo = yield getFoo()
    console.log(foo)
  } catch(e) {
    console.log(e)
  }
}

function run(generator) {
  var it = generator()
  
  function go(result) {
    if (result.done) return result.value

    return result.value.then( function(value) {
      return go(it.next(value))
    }, function (error) {
      return go(it.throw(error))
    })
  }
  go(it.next())
}

run(g)

Generator 函數(shù)g 中有一個異步操作getFoo折汞,它返回的就是一個 Promise 對象盖腿。函數(shù) run 用來處理這個 Promise 對象,并調(diào)用下一個 next 方法。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末揖庄,一起剝皮案震驚了整個濱河市欠雌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌富俄,老刑警劉巖而咆,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暴备,居然都是意外死亡,警方通過查閱死者的電腦和手機涯捻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來障癌,“玉大人,你說我怎么就攤上這事康辑。” “怎么了疮薇?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵我注,是天一觀的道長。 經(jīng)常有香客問我仓手,道長,這世上最難降的妖魔是什么嗽冒? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任添坊,我火速辦了婚禮剿另,結果婚禮上,老公的妹妹穿的比我還像新娘谚攒。我一直安慰自己,他們只是感情好馏臭,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布讼稚。 她就那樣靜靜地躺著,像睡著了一般锐想。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赠摇,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音烫罩,去河邊找鬼耘戚。 笑死嗡髓,一個胖子當著我的面吹牛收津,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撞秋,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼吻贿,長吁一口氣:“原來是場噩夢啊……” “哼串结!你這毒婦竟也來了舅列?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤把敞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后奋早,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盛霎,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡愤炸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年掉奄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挥萌。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖引瀑,靈堂內(nèi)的尸體忽然破棺而出榨馁,到底是詐尸還是另有隱情,我是刑警寧澤翼虫,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站掸宛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏唧瘾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一饰序、第九天 我趴在偏房一處隱蔽的房頂上張望规哪。 院中可真熱鬧,春花似錦诉稍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舔箭。三九已至蚊逢,卻和暖如春箫章,著一層夾襖步出監(jiān)牢的瞬間烙荷,已是汗流浹背檬寂。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昼伴,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓圃郊,卻偏偏與公主長得像女蜈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子伪窖,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349