promise的原理以及實(shí)現(xiàn)(一)劝篷,看不懂來找我

Promise主要作用:把異步操作變?yōu)楹唵慰煽兀谕瓿僧惒讲僮骱笸ㄟ^then可以做你想的操作通今。解決了地獄回調(diào)的痛點(diǎn)粥谬。

本篇實(shí)現(xiàn)了Promise的基本方法resolvereject .then()辫塌、.then().then()鏈?zhǔn)秸{(diào)用漏策。

一、Promise概念原理:

遵循Promise/A+規(guī)則:https://promisesaplus.com
它代表了一個異步操作的最終完成或者失敗臼氨。只接受一個函數(shù)(內(nèi)部叫executor自動執(zhí)行)掺喻,并且函數(shù)有兩個參數(shù):resolve(成功)、reject(失敶⒕亍)感耙。
記住,只要聲明了一個Promise即new Promise()持隧,他就會立即執(zhí)行抑月!
執(zhí)行時內(nèi)部有三種狀態(tài),pending表示等待中舆蝴、fulfilled表示成功谦絮、rejected表示失敗题诵。
它的結(jié)果是一個明確的狀態(tài):

  • pending => fulfilled
  • pending => rejected
    聽起來它的內(nèi)部有點(diǎn)像薛定諤的貓
    只要成功了,永遠(yuǎn)都是成功层皱,失敗了永遠(yuǎn)都是失敗性锭,狀態(tài)已經(jīng)改變就不能再改變。

二叫胖、基本使用:

1草冈、一般我們使用它都需要與.then()方法一起食用,其中.then()也是接受兩個可選的參數(shù):fulfilled(promise成功時候的回調(diào)函數(shù))瓮增、rejected(promise失敗時候的回調(diào)函數(shù))怎棱。如果傳入then的參數(shù)不是一個函數(shù),則會忽略它绷跑。

// promise.then語法
new Promise((resolve, reject) => {
  reject(1);  // 或是resolve(1)
}).then(res => {
  console.log('fulfillment', res);
}, err => {
  console.log('rejection', err);
});

// resolve表示成功拳恋,可以通過.then()方法獲取到成功的結(jié)果
new Promise((resolve, reject) => {
  resolve(1);
}).then(res => console.log(res));  // 1


// reject表示失敗,使用.catch()方法獲取到失敗錯誤原因
new Promise((resolve, reject) => {
  reject(2);
}).catch(err => console.log(err));   // 2

2砸捏、支持鏈?zhǔn)绞褂?/p>

new Promise((resolve, reject) => {
  resolve(1);
}).then(res => res).then(res => console.log(res));  // 1

//如果不return一個結(jié)果谬运,默認(rèn)返回的是一個undefind
new Promise((resolve, reject) => {
  resolve(1);
}).then(res => {}).then(res => console.log(res));   // undefind

三、實(shí)現(xiàn)環(huán)節(jié)

1垦藏、初步結(jié)構(gòu)

按照上面我們已經(jīng)知道Promise內(nèi)部的一些內(nèi)容梆暖,寫一個方法架構(gòu)出來。
它需要有:三種狀態(tài)(pending掂骏、fulfilled轰驳、rejected)、默認(rèn)值(成功/失敗的默認(rèn)返回值undefind)弟灼、默認(rèn)方法(executor滑废、resolve、reject 袜爪、then)先寫上去。

class MyPromise {

  /**
   * 內(nèi)部三種狀態(tài)
   * @type {string}
   */
  static pending = 'pending';
  static fulfilled = 'fulfilled';
  static rejected = 'rejected';

  constructor(executor) {
    this.status = MyPromise.pending;  //默認(rèn)的狀態(tài)是pending
    this.susecessValue = undefined;  // 成功默認(rèn)返回是undefined
    this.failedValue = undefined;  // 失敗默認(rèn)返回是undefined
    executor(this.resolve, this.reject);  //自動執(zhí)行
  }

  /**
   * 成功的方法
   * @param res
   */
  resolve = (res) => {

  };

  /**
   * 失敗的方法
   * @param err
   */
  reject = (err) => {

  };

  /**
   * 獲取成功結(jié)果的then方法
   * @param onResolved
   * @param onRejected
   */
  then = (onResolved, onRejected) => {

  };
}
2薛闪、接著把resolve、reject 、then方法補(bǔ)充完整疹尾,很簡單秘豹,只需要判斷它的狀態(tài)。resolve把狀態(tài)改為fulfilled成功诱咏,同時把值存起來苔可;reject 把狀態(tài)改為rejected,同時把值存起來袋狞。then方法分別判斷焚辅,是成功還是還是失敗映屋,去運(yùn)行then((res)=>{})傳進(jìn)來的方法就可以。
class MyPromise {

  static pending = 'pending';
  static fulfilled = 'fulfilled';
  static rejected = 'rejected';

  constructor(executor) {
    this.status = MyPromise.pending;
    this.susecessValue = undefined;
    this.failedValue = undefined;
    executor(this.resolve, this.reject);
  }

  resolve = (res) => {
    if (this.status === 'pending') {
      this.susecessValue = res;
      this.status = MyPromise.fulfilled;  // 成功了直接切換狀態(tài)同蜻,因?yàn)閠hen()方法需要使用狀態(tài)
    }
  };

  reject = (err) => {
    if (this.status === 'pending') {
      this.failedValue = err;
      this.status = MyPromise.rejected; // 失敗了直接切換狀態(tài)棚点,因?yàn)閠hen()方法需要使用狀態(tài)
    }
  };

  then = (onResolved, onRejected) => {
    if (this.status === 'fulfilled' && onResolved) {
      onResolved(this.susecessValue);
    }
    if (this.status === 'rejected' && onRejected) {
      onRejected(this.failedValue);
    }
  };
}

到這里算是最基本的一個promise完成了,我們來運(yùn)行看一下:

new MyPromise((resolve, reject) => {
  resolve('成功1111');
}).then(res => {
  console.log('fulfillment', res);  // fulfillment 成功1111
}, err => {
  console.log('rejection', err);
});
new MyPromise((resolve, reject) => {
  reject('失敗222');
}).then(res => {
  console.log('fulfillment', res);
}, err => {
  console.log('rejection', err);  //  rejection 失敗222
});

通過運(yùn)行是沒有問題的湾蔓,到這里我們算是完成了第一個小目標(biāo)瘫析。
但是如果此時我們碰到了setTimeout就會有很大麻煩。比如resolve是寫在setTimeout里的:

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('測試');
  }, 3000);
}).then(res => {
  console.log('fulfillment', res);
}, err => {
  console.log('rejection', err);
});

我們會發(fā)現(xiàn)該方法并不會運(yùn)行默责,原因很簡單贬循,因?yàn)榇藭r的resolve('測試')方法被延遲了3秒才執(zhí)行,然而我們寫的then是沒有被延遲的桃序,所以這時候杖虾,then()方法會先執(zhí)行,但是因?yàn)槲覀兊?code>then內(nèi)部寫了this.status狀態(tài)判斷(此時resolve還沒有把默認(rèn)的狀態(tài)statuspending改為fulfilled)所以它不執(zhí)行內(nèi)部的任何一個方法葡缰。

3亏掀、增加支持異步(重點(diǎn)難點(diǎn))

我們可以把then(x = > x, y=> x)方法中的兩個參數(shù)(都是函數(shù))先存起來。等待resolve或者reject的時候再運(yùn)行泛释。

class MyPromise {

  static pending = 'pending';
  static fulfilled = 'fulfilled';
  static rejected = 'rejected';

  constructor(executor) {
    this.onFulfilledFoo = [];  // 存儲成功的方法
    this.onRejectedFoo = [];  // 存儲失敗的方法
    this.status = MyPromise.pending;
    this.susecessValue = undefined;
    this.failedValue = undefined;
    executor(this.resolve, this.reject);
  }

  resolve = (res) => {
    if (this.status === 'pending') {
      this.susecessValue = res;
      this.status = MyPromise.fulfilled; 
      // resolve 時運(yùn)行我們存儲過的對應(yīng)onResolved方法,注意要把參數(shù)傳遞給fn
      this.onFulfilledFoo.forEach(fn => fn(res)); 
    }
  };

  reject = (err) => {
    if (this.status === 'pending') {
      this.failedValue = err;
      this.status = MyPromise.rejected;
      // 同理滤愕,reject時就去運(yùn)行我們存儲起來的對應(yīng)onRejected方法,注意要把參數(shù)傳遞給fn
      this.onRejectedFoo.forEach(fn => fn(err)); 
    }
  };

  then = (onResolved, onRejected) => {
  // 如果是pending狀態(tài),把成功的方法通過數(shù)組存起來
    if (this.status === 'pending' && onResolved) {
      this.onFulfilledFoo.push(onResolved);
    }
  // 如果是pending狀態(tài)怜校,把失敗的方法通過數(shù)組存起來
    if (this.status === 'pending' && onRejected) {  
      this.onRejectedFoo.push(onRejected);
    }
    if (this.status === 'fulfilled' && onResolved) {
      onResolved(this.susecessValue);
    }
    if (this.status === 'rejected' && onRejected) {
      onRejected(this.failedValue);
    }
  };
}

然后再來測試下我們剛才遇到的 setTimeout問題:

new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('測試');
  }, 3000);
}).then(res => {
  console.log('fulfillment', res);   // 測試
}, err => {
  console.log('rejection', err);
});

很完美间影,3秒后打印出‘測試’兩個字,這就是我們要的結(jié)果茄茁。但是此時還有一個大問題魂贬,就是我們還不能支持鏈?zhǔn)秸{(diào)用。比如說以下這種情況:

function foo() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve('返回結(jié)果');
    }, 3000);
  });
}

foo().then(res => {
  console.log('1', res);
  return res;
}).then(res => res);  //這里的then會報錯:Cannot read properties of undefined (reading 'then')

我們想到是否可以直接在我們寫的promise中then方法直接return一個this裙顽,是可以的付燥。但是解決不了問題。因?yàn)橛龅揭韵逻@個情況就涼涼了:

function foo() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve('測試');
    }, 3000);
  });
}

foo().then(res => {
  return res + '1111';
}).then(res => console.log(res));  // 測試
// 正確結(jié)果應(yīng)該是:測試1111

很顯然這種結(jié)果不是我們想要的愈犹,因?yàn)槲覀兊膖hen執(zhí)行完后沒有把后續(xù)的then繼續(xù)把方法放到promise里面執(zhí)行(理解為現(xiàn)在的結(jié)果是在promise外部執(zhí)行的)键科。所以我們需要在任何時候都返回一個promise,以供then鏈?zhǔn)秸{(diào)用漩怎。

4勋颖、增加支持鏈?zhǔn)秸{(diào)用(重點(diǎn))

我們需要先改造一下剛剛的寫法,1勋锤、then永遠(yuǎn)返回類實(shí)例本身(只有這樣才可以為無限.then().then()調(diào)用)饭玲;如果是第一次調(diào)用then(即狀態(tài)為pending,此時promise內(nèi)部還沒給出結(jié)果) 就把then方法用來做存儲接收到的方法操作叁执,即外部傳進(jìn)來來的方法都是用then存儲茄厘。 否則就直接執(zhí)行_handle方法(即異步完成了矮冬,后面的.then可以直接執(zhí)行),2蚕断、resolve欢伏、reject負(fù)傳遞剛剛通過then存儲的傳進(jìn)來的方法給_handle,3(重點(diǎn))亿乳、_handle負(fù)責(zé)判斷成功或者失敗情況下該執(zhí)行哪個對應(yīng)的方法硝拧。并且多了一步把then傳進(jìn)來的方法里面添加計(jì)算好的返回值。

class MyPromise {

  static pending = 'pending';
  static fulfilled = 'fulfilled';
  static rejected = 'rejected';

  constructor(executor) {
    this.saveFoo = []; // 只需要一個就可以存儲
    this.status = MyPromise.pending;
    this.susecessValue = undefined;
    this.failedValue = undefined;
    executor(this.resolve, this.reject);
  }

  resolve = (res) => {
    if (this.status === 'pending') {
      this.susecessValue = res;
      this.status = MyPromise.fulfilled;
      // 此時調(diào)用我們的handle去觸發(fā)外部傳進(jìn)來的方法
      this.saveFoo.forEach(fn => this._handle(fn));  
    }
  };

  reject = (err) => {
    if (this.status === 'pending') {
      this.failedValue = err;
      this.status = MyPromise.rejected;
      this.saveFoo.forEach(fn => this._handle(fn));  //同理
    }
  };

  /**
   * 如果是pending狀態(tài)(即第一次調(diào)用then葛假,promise內(nèi)部還沒給出結(jié)果)
   * 就把then方法用來做存儲接收到的方法操作障陶,即外部傳進(jìn)來來的方法都是用then存儲
   * 否則就直接執(zhí)行_handle方法(即異步完成了,后面的.then可以直接執(zhí)行)
   * @param onResolved
   * @param onRejected
   */
  then = (onResolved, onRejected) => {
    return new MyPromise((nextResolve, nexReject) => {
      if (this.status === 'pending') {
        this.saveFoo.push({onResolved, onRejected, nextResolve, nexReject});
      } else {
        this._handle({onResolved, onRejected, nextResolve, nexReject});
      }
    });
  };

  /**
   * 負(fù)責(zé)執(zhí)行成功或者失敗后的方法
   * @param callbacks
   * @returns {MyPromise}
   * @private
   */
  _handle = (callbacks) => {
    const { onResolved, onRejected, nextResolve, nexReject } = callbacks;

    if (this.status === 'fulfilled' && onResolved) {
      // 判斷是否有方法聊训,有的話和我們最開始的一樣傳入值抱究,否則返回默認(rèn)值
      const thenValue = onResolved ? onResolved(this.susecessValue) : this.susecessValue;
      // 把最開始得到的值繼續(xù)傳遞給下一個then中傳遞進(jìn)來的方法
      nextResolve(thenValue);
    }
    // 同理
    if (this.status === 'rejected' && onRejected) {
      const thenErr = onRejected ? onRejected(this.failedValue) : this.failedValue;
      nexReject(thenErr);
    }
  };
}

再次測試一下:

function foo() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve('測試');
    }, 3000);
  });
}

foo().then(res => {
  console.log('結(jié)果:', res);
  return res + '1111';
}).then(res => console.log('結(jié)果:', res));
// 結(jié)果: 測試
// 結(jié)果: 測試1111

到這里,我們算是解決了then示例調(diào)用的難題带斑,還有一種情況鼓寺,就是當(dāng)我們的第二個then里面resolve的是一個Promise而不是一個值的時候,比如:

function foo() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve('測試');
    }, 3000);
  });
}

foo().then(res => { 
  return new MyPromise((resolve, reject) => { // 如果這里再返回一個promise勋磕,我們就需要判斷
    resolve('測試222');
  });
}).then(res => console.log('結(jié)果:', res));

我們就需要對它判斷一下妈候,如果是一個promise實(shí)例就直接去resolve或者reject返回結(jié)果,于是代碼里面加個promiseToThen方法判斷是否是實(shí)例本身挂滓,是的話就去走then方法返回結(jié)果苦银。

class MyPromise {

  static pending = 'pending';
  static fulfilled = 'fulfilled';
  static rejected = 'rejected';

  constructor(executor) {
    this.saveFoo = []; // 只需要一個就可以存儲
    this.status = MyPromise.pending;
    this.susecessValue = undefined;
    this.failedValue = undefined;
    executor(this.resolve, this.reject);
  }

  resolve = (res) => {
    this.promiseToThen(res); // 判斷是否是一個promise
    if (this.status === 'pending') {
      this.susecessValue = res;
      this.status = MyPromise.fulfilled;
      this.saveFoo.forEach(fn => this._handle(fn)); 
    }
  };

  reject = (err) => {
    this.promiseToThen(err); // 判斷是否是一個promise
    if (this.status === 'pending') {
      this.failedValue = err;
      this.status = MyPromise.rejected;
      this.saveFoo.forEach(fn => this._handle(fn));  //同理
    }
  };

  /**
   * 如果是一個promise的本身實(shí)例就走then
   * @param Params
   */
  promiseToThen = (Params) => {
    if (Params instanceof MyPromise) {
      Params.then(this.resolve, this.reject);
    }
  };

  /**
   * 如果是pending狀態(tài)(即第一次調(diào)用then,promise內(nèi)部還沒給出結(jié)果)
   * 就把then方法用來做存儲接收到的方法操作赶站,即外部傳進(jìn)來來的方法都是用then存儲
   * 否則就直接執(zhí)行_handle方法(即異步完成了幔虏,后面的.then可以直接執(zhí)行)
   * @param onResolved
   * @param onRejected
   */
  then = (onResolved, onRejected) => {
    return new MyPromise((nextResolve, nexReject) => {
      if (this.status === 'pending') {
        this.saveFoo.push({onResolved, onRejected, nextResolve, nexReject});
      } else {
        this._handle({onResolved, onRejected, nextResolve, nexReject});
      }
    });
  };

  /**
   * 負(fù)責(zé)執(zhí)行成功或者失敗后的方法
   * @param callbacks
   * @returns {MyPromise}
   * @private
   */
  _handle = (callbacks) => {
    const { onResolved, onRejected, nextResolve, nexReject } = callbacks;

    if (this.status === 'fulfilled' && onResolved) {
      // 判斷是否有方法,有的話和我們最開始的一樣傳入值贝椿,否則返回默認(rèn)值
      const thenValue = onResolved ? onResolved(this.susecessValue) : this.susecessValue;
      // 把最開始得到的值繼續(xù)傳遞給下一個then中傳遞進(jìn)來的方法
      nextResolve(thenValue);
    }
    // 同理
    if (this.status === 'rejected' && onRejected) {
      const thenErr = onRejected ? onRejected(this.failedValue) : this.failedValue;
      nexReject(thenErr);
    }
  };
}

最后想括,我們還有一個步驟沒做,就是promise規(guī)定烙博,如果then的參數(shù)不是一個函數(shù)而是一個具體的值瑟蜈,我們就需要忽略并且返回對應(yīng)的結(jié)果;如果then()參數(shù)為空那么這個then可以不執(zhí)行习勤,直接返回對應(yīng)結(jié)果就可以。比如

.then(res=>'下一個then返回一個具體數(shù)值').then(1).then(res=>console.log(res))
// 或者是這種情況
.then(res=>'下一個then參數(shù)為空').then().then(res=>console.log(res))

我們只需要在_handle方法處加上判斷即可焙格,最終代碼如下:

class MyPromise {

  static pending = 'pending';
  static fulfilled = 'fulfilled';
  static rejected = 'rejected';

  constructor(executor) {
    this.saveFoo = []; // 只需要一個就可以存儲
    this.status = MyPromise.pending;
    this.susecessValue = undefined;
    this.failedValue = undefined;
    try {
      executor(this.resolve, this.reject);
    } catch (e) {
      this.reject(e)
    }
  }

  resolve = (res) => {
    this.promiseToThen(res); // 判斷是否是一個promise
    if (this.status === 'pending') {
      this.susecessValue = res;
      this.status = MyPromise.fulfilled;
      this.saveFoo.forEach(fn => this._handle(fn)); 
    }
  };

  reject = (err) => {
    this.promiseToThen(err); // 判斷是否是一個promise
    if (this.status === 'pending') {
      this.failedValue = err;
      this.status = MyPromise.rejected;
      this.saveFoo.forEach(fn => this._handle(fn));  //同理
    }
  };

  /**
   * 如果是一個promise的本身實(shí)例就走then
   * @param Params
   */
  promiseToThen = (Params) => {
    if (Params instanceof MyPromise) {
      Params.then(this.resolve, this.reject);
    }
  };


  /**
   * 把then方法用來做存儲接收到的方法操作图毕,即外部傳進(jìn)來來的方法都是用then存儲
   * @param onResolved
   * @param onRejected
   */
  then = (onResolved, onRejected) => {
    return new MyPromise((nextResolve, nexReject) => {
      if (this.status === 'pending') {
        this.saveFoo.push({ onResolved, onRejected, nextResolve, nexReject });
      }
      this._handle({ onResolved, onRejected, nextResolve, nexReject });
    });
  };

  _handle = (callbacks) => {
    const {onResolved, onRejected, nextResolve, nexReject} = callbacks;
    if (typeof onResolved === 'undefined') { // 直接執(zhí)行下一個then方法中的函數(shù)
      typeof nextResolve === 'function' && nextResolve(this.susecessValue)
    }

  /**
   * 負(fù)責(zé)執(zhí)行成功或者失敗后的方法
   * @param callbacks
   * @returns {MyPromise}
   * @private
   */
    if (this.status === 'fulfilled' && onResolved) {
      // 如果參數(shù)不是一個函數(shù)
      const translateFun = typeof onResolved === 'function' ? onResolved : () => onResolved;
      // 判斷是否有方法,有的話和我們最開始的一樣傳入值眷唉,否則返回默認(rèn)值
      const thenValue = onResolved ? translateFun(this.susecessValue) : this.susecessValue;
      // 把最開始得到的值繼續(xù)傳遞給下一個then中傳遞進(jìn)來的方法
      nextResolve(thenValue);
    }
    // 同理
    if (this.status === 'rejected' && onRejected) {
      const translateFun = typeof onRejected === 'function' ? onRejected : () => onRejected;
      const thenErr = onRejected ? translateFun(this.failedValue) : this.failedValue;
      nexReject(thenErr);
    }
  };
}

最后:提示:任何手寫的promise無法達(dá)到與原生的promise的運(yùn)行順序一致的效果(但是我們能保證then是在異步回調(diào)后出發(fā)予颤,這其實(shí)是promise的一個重要點(diǎn))囤官,因?yàn)樵膒romise里.then方法會被歸類到微任務(wù)那里,導(dǎo)致最終運(yùn)行順序不一致類似這種蛤虐。

new Promise(resolve=>resolve(1)).then(res=>console.log(1))
console.log(2)
// 2  1

new MyPromise(resolve=>resolve(1)).then(res=>console.log(1))
console.log(2)
// 1  2
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末党饮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子驳庭,更是在濱河造成了極大的恐慌刑顺,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饲常,死亡現(xiàn)場離奇詭異蹲堂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)贝淤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門柒竞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人播聪,你說我怎么就攤上這事朽基。” “怎么了离陶?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵稼虎,是天一觀的道長。 經(jīng)常有香客問我枕磁,道長渡蜻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任计济,我火速辦了婚禮茸苇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沦寂。我一直安慰自己学密,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布传藏。 她就那樣靜靜地躺著腻暮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪毯侦。 梳的紋絲不亂的頭發(fā)上哭靖,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音侈离,去河邊找鬼试幽。 笑死,一個胖子當(dāng)著我的面吹牛卦碾,可吹牛的內(nèi)容都是我干的铺坞。 我是一名探鬼主播起宽,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼济榨!你這毒婦竟也來了坯沪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤擒滑,失蹤者是張志新(化名)和其女友劉穎腐晾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體橘忱,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赴魁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了钝诚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颖御。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖凝颇,靈堂內(nèi)的尸體忽然破棺而出潘拱,到底是詐尸還是另有隱情,我是刑警寧澤拧略,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布芦岂,位于F島的核電站,受9級特大地震影響垫蛆,放射性物質(zhì)發(fā)生泄漏禽最。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一袱饭、第九天 我趴在偏房一處隱蔽的房頂上張望川无。 院中可真熱鬧,春花似錦虑乖、人聲如沸懦趋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仅叫。三九已至,卻和暖如春糙捺,著一層夾襖步出監(jiān)牢的瞬間诫咱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工洪灯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坎缭,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像幻锁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子边臼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容