不积跬步之Promise输出题(共32道有详细解析版)

promise.jpeg

笔者在把手写Promise源码拿下以后,下面的这些题才融会贯通.如果发现实在理解不了,可以先去学习一下手写Promise系列.然后在做题.

1.考察点:只有调用resolve或者reject才会改变状态,触发回调

const promise = new Promise((resolve, reject) => {
  console.log(1);
  console.log(2);
});
promise.then(() => {
  console.log(3);
});
console.log(4);

输出为:

1
2
4

为什么没有3这就是这道题坑的地方,考察的是你是否知道,Promise只有在调用了resolve,或者reject这两个回调,才可以改变状态,触发微任务的的回调。

2.考察点:Promisethen后面的状态,是由其中的回调函数决定的。

const promise1 = new Promise((resolve, reject) => {
  console.log('promise1')
  resolve('resolve1')
})
const promise2 = promise1.then(res => {
  console.log(res)
})
console.log('1', promise1);
console.log('2', promise2);

输出:

promise1
1 Promise{<resolved>: resolve1}
2 Promise{<pending>}
resolve1

描述一下流程:

1.script是一个宏任务,按照顺序执行这些代码
2.首先进入Promise执行构造函数,打印promise1
3.同步执行resolve("resolve"),改变Promise状态为Resolved。同时触发回调。
4.碰到promise1.then这个微任务,将它放入微任务队列。
5.执行同步代码1,输出promise1的状态,它的状态已经确定为Resolved
6.执行同步代码2,输出promise2的状态,它的状态因为需要微任务队列中的回调执行完成之后才能知道
所以打印出来的是pending状态的promise.
7.宏任务执行完毕,开始执行微任务,这个时候开始执行console.log(res).而res的值是resolve1.
8.如果我们延迟打印Promise2的状态,那么它最后也会变成Resolved,如果回调中返回的是非Promise的数据,包括Undefined。那么
状态就是resolved

这道题考察的是:Promisethen后面的状态,是由其中的回调函数决定的。
1.如果是非Promise.则状态为resolved
2.如果是Promise,则取决于该Promise的状态
3.如果没有执行,则状态是pending,需要等到微任务队列回调完成。
4.如果里面报错 ,或者抛出错误,状态会变为rejected

3.考察点:resolve执行

const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log("timerStart");
    resolve("success");
    console.log("timerEnd");
  }, 0);
  console.log(2);
});
promise.then((res) => {
  console.log(res);
});
console.log(4);

输出结果:

1
2
4
timerStart
timerEnd
success

代码执行过程如下:

1.执行Promise的构造函数,它是同步执行的。所以打印 1
2.碰到setTimeout,假如宏任务队列。
3.打印出2
4.碰到 promise.then,但是它需要等到微任务队列的执行回调。
5.打印4
6.宏任务执行完毕,没有微任务,执行setTimeout.打印timerStart
7.执行resolve回调,改变Promise的内部状态为resolved,同时把回调任务压入微任务队列。
8.继续执行打印timerEnd
9.宏任务执行完毕,检查微任务对比。打印console.log(res).

这道题考察的是Promiseresolve执行完毕之后,是先去执行回调了呢?还是继续往下执行。

因为它的回调实际上是压入微任务队列执行的,所以并不是马上执行。应该是继续往下执行。

4.考察点:微任务和宏任务的执行

Promise.resolve().then(() => {
  console.log('promise1');
  const timer2 = setTimeout(() => {
    console.log('timer2')
  }, 0)
});
const timer1 = setTimeout(() => {
  console.log('timer1')
  Promise.resolve().then(() => {
    console.log('promise2')
  })
}, 0)
console.log('start');

输出结果

start
promise1
timer1
promise2
timer2

代码执行过程如下:

1.首先Promise.resolve().then会在微任务队列中添加一个任务.
2.执行time1.给宏任务队列添加一个任务
3.打印start
4.本轮宏任务执行完毕,开始检查微任务队列,执行打印promise1
5.执行time2,在宏任务队列中添加任务.
6.微任务执行完毕.开始执行宏任务.会先执行先添加到宏任务队列的代码.打印time1.
7.执行Promise.resolve().then,在本轮宏任务中的微任务队列添加任务.
8.宏任务执行完毕,检查执行微任务队列.打印promsie2.
9.微任务执行完毕,执行宏任务,打印time2.

这道题考察的是Promise.resolve()的执行会返回一个resolve状态的Promise.
同时会调用它的then方法中的回调函数,把一个微任务添加到微任务队列中去.

另外,宏任务执行完毕之后,会先执行微任务队列.

5.考察点:Promise的状态

const promise = new Promise((resolve, reject) => {
    resolve('success1');
    reject('error');
    resolve('success2');
});
promise.then((res) => {
    console.log('then:', res);
}).catch((err) => {
    console.log('catch:', err);
})

输出:

then:success1

本题考察的点是:Promise的状态只可以改变一次,所以,后面的代码都不会在执行.

6.考察点:值穿透

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)

输出结果:

1
Promise {<fulfilled>: undefined}

考察点:值穿透

这道题的意思是,如果then方法的参数不是函数,那么它是失效状态.
Promise的值会一直往下传,直到传到一个函数里面.

7.考察点:Promise的状态

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
const promise2 = promise1.then(() => {
  throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {
  console.log('promise1', promise1)
  console.log('promise2', promise2)
}, 2000)

输出结果

promise1 Promise {<pending>}
promise2 Promise {<pending>}

Uncaught (in promise) Error: error!!!
promise1 Promise {<fulfilled>: "success"}
promise2 Promise {<rejected>: Error: error!!}

考察点:抛出错误也会改变Promise的状态

8.考察点:Promisecatch和它的位置没有关系

Promise.resolve(1)
  .then(res => {
    console.log(res);
    return 2;
  })
  .catch(err => {
    return 3;
  })
  .then(res => {
    console.log(res);
  });
1
2

Promise是可以链式调用的.同时catch的回调和它的位置没有关系,只有它的状态变为rejected才会调用.

9.考察点:then的结果由其返回值决定.

Promise.resolve().then(() => {
  return new Error('error!!!')
}).then(res => {
  console.log("then: ", res)
}).catch(err => {
  console.log("catch: ", err)
})

//"then: " "Error: error!!!"

返回任意一个非 promise 的值都会被包裹成 promise 对象,因此这里的return new Error('error!!!')也被包裹成了return Promise.resolve(new Error('error!!!')),因此它会被then捕获而不是catch。

10.考察点:Promise不能返回它自己

const promise = Promise.resolve().then(() => {
  return promise;
})
promise.catch(console.err)

//Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>

这里其实是一个坑,.then或者.catch返回的值不能是promise本身.否则会报错.

11.考察点:值穿透

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)
  
  //1

看到这个题目,好多的then,实际上只需要记住一个原则:.then 或.catch 的参数期望是函数,传入非函数则会发生值透传。

第一个then和第二个then中传入的都不是函数,一个是数字,一个是对象,因此发生了透传,将resolve(1) 的值直接传到最后一个then里,直接打印出1。

12.考察点:then方法的第二个回调参数

Promise.reject('err!!!')
  .then((res) => {
    console.log('success', res)
  }, (err) => {
    console.log('error', err)
  }).catch(err => {
    console.log('catch', err)
  })
  
//  error err!!!

考察点:
.then方法其实是有两个两个回调函数,第二个回调函数处理失败的情况.
如果这个函数又,则就不会再调用catch方法.

Promise.resolve()
  .then(function success (res) {
    throw new Error('error!!!')
  }, function fail1 (err) {
    console.log('fail1', err)
  }).catch(function fail2 (err) {
    console.log('fail2', err)
  })

如果是在then方法的第一个参数中抛出错误,那么就不会在第二个参数中捕获了,而是被catch捕获

13.考察点 :finally

Promise.resolve('1')
  .then(res => {
    console.log(res)
  })
  .finally(() => {
    console.log('finally')
  })
Promise.resolve('2')
  .finally(() => {
    console.log('finally2')
    return '我是finally2返回的值'
  })
  .then(res => {
    console.log('finally2后面的then函数', res)
  })

输出结果:

1
finally2后面的then函数 2
finally
finally2

.finally一般用的很少,只需要记住一下几点就可以了:

  • .finally方法不管Promise对象的状态如何都会执行.
  • .finally方法的回调函数不接受任何参数,也就是说你在.finally()函数中是无法知道Promise最终的状态是resolved还是rejected的.
  • 它最终返回的默认会是一个上一次的Promise对象值,不过如果抛出的是一个异常则返回异常的Promise对象。
  • finally本质上是then方法的特例.所以它也会被按照then方法那样,按个去插入微任务队列中执行.而不是像catch那样.

.finally的错误捕获:

Promise.resolve('1')
  .finally(() => {
    console.log('finally1')
    throw new Error('我是finally中抛出的异常')
  })
  .then(res => {
    console.log('finally后面的then函数', res)
  })
  .catch(err => {
    console.log('捕获错误', err)
  })

14.考察点:Promise.all的特性

function runAsync (x) {
    const p = new Promise(r => setTimeout(() => 
    r(x, console.log(x)), 1000))
    return p
}

Promise.all([runAsync(1), runAsync(2), runAsync(3)]).then(res => console.log(res))

输出结果:

1
2
3
[1, 2, 3]

首先,定义了一个Promise,来异步执行函数runAsync,该函数传入一个值x,然后间隔一秒后打印出这个x。

之后再使用Promise.all来执行这个函数,执行的时候,看到一秒之后输出了1,2,3,同时输出了数组[1, 2, 3],三个函数是同步执行的,并且在一个回调函数中返回了所有的结果。并且结果和函数的执行顺序是一致的。

15.考察点:Promise.all的错误处理

function runAsync (x) {
  const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))
  return p
}
function runReject (x) {
  const p = new Promise((res, rej) => setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x))
  return p
}
Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)])
       .then(res => console.log(res))
       .catch(err => console.log(err))

输出结果

// 1s后输出
1
3
// 2s后输出
2
Error: 2
// 4s后输出
4

可以看到。catch捕获到了第一个错误,在这道题目中最先的错误就是runReject(2)的结果。如果一组异步操作中有一个异常都不会进入.then()的第一个回调函数参数中。会被.then()的第二个回调函数捕获。

16:考察点:Promise.race的竞争

function runAsync (x) {
  const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))
  return p
}
Promise.race([runAsync(1), runAsync(2), runAsync(3)])
  .then(res => console.log('result: ', res))
  .catch(err => console.log(err))

输出结果:

1
'result: ' 1
2
3

then只会捕获第一个成功的方法,其他函数虽然还会继续执行,但是并不会被then捕获了.

17.考察点:Promise.race

function runAsync(x) {
  const p = new Promise(r =>
    setTimeout(() => r(x, console.log(x)), 1000)
  );
  return p;
}
function runReject(x) {
  const p = new Promise((res, rej) =>
    setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x)
  );
  return p;
}
Promise.race([runReject(0), runAsync(1), runAsync(2), runAsync(3)])
  .then(res => console.log("result: ", res))
  .catch(err => console.log(err));

输出:

0
Error: 0
1
2
3

由于竞争关系,第一个执行完的决定Promise.race的状态.
所以它会回调catch.

其他的任务虽然会继续执行,但是由于Promise的状态只能改变一次的特性.

已经不会被处理

18. 考察点:async/await

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}
async function async2() {
  console.log("async2");
}
async1();
console.log('start')

输出结果:

async1 start
async2
start
async1 end"

执行过程如下:
1.首先执行函数中的同步代码async1 start,之后遇到了await,它会阻塞async1后面代码的执行,因此会先去执行async2中的同步代码async2,然后跳出async1

2.跳出async1函数后,执行同步代码start

3.在一轮宏任务全部执行完之后,再来执行await后面的内容async1 end。

这里可以理解为,await后面的语句想防御放入了new Promise中.如果它里面有异步代码,那么就会异步执行,如果是同步,当时就是同步执行了.

而下一行及之后的代码,就相当于放入了Promise.then中了.

19.考察点:async/await

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
  setTimeout(() => {
    console.log('timer1')
  }, 0)
}
async function async2() {
  setTimeout(() => {
    console.log('timer2')
  }, 0)
  console.log("async2");
}
async1();
setTimeout(() => {
  console.log('timer3')
}, 0)
console.log("start")

输出结果:

async1 start
async2
start
async1 end
timer2
timer3
timer1

代码执行过程如下:

  1. 执行async1()同步执行里面的代码,打印async1 start"
  2. 碰到await async2(); 执行里面的代码,碰到setTimeout,在宏任务队列中添加任务
  3. 打印async2
  4. async2执行完毕,返回值为undefined,所以它后面的代码挂起加入微任务队列
  5. 添加宏任务time3
  6. 打印start
  7. 本轮宏任务执行完毕,开始执行微任务队列.打印async1 end,
  8. 添加宏任务time1
  9. 微任务队列执行完毕,开始执行宏任务,打印之前加入的顺序.time2,time3,time1

20.考察点:await的状态由其后面跟着的东西决定.

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1')
  })
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

输出结果:

srcipt start
async1 start
promise1
srcipt end
async1 success
async1 end

我这里做错了.这里需要注意 await 如果后面跟着的是一个Promise,
那么它的状态由这个Promise的状态决定.里面的代码可以看到,那个Promise并没有改变状态,调用resolve.所以它的状态一直都是pending.

所以它后面的代码都不会执行,包括了then方法里面的代码.

正确的结果应该是:

script start
async1 start
promise1
script end

21:考察点:await的状态由其后面跟着的东西决定.

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1')
    resolve('promise1 resolve')
  }).then(res => console.log(res))
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

输出结果:

srcipt start
async1 start'
promise1
srcipt end
promise1 resolve
async1 success
async1 end

和上面的题类似,区别只是 添加了resolve来改变状态.

22.考察点:经典面试题

这个就是拿到经典面试题了.

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}

async function async2() {
  console.log("async2");
}

console.log("script start");

setTimeout(function() {
  console.log("setTimeout");
}, 0);

async1();

new Promise(resolve => {
  console.log("promise1");
  resolve();
}).then(function() {
  console.log("promise2");
});
console.log('script end')

输出结果:

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

代码执行过程:

  1. 开头定义了async1async2两个函数,但是并未执行,执行script中的代码,所以打印出script start
  2. 遇到定时器Settimeout,它是一个宏任务,将其加入到宏任务队列;
  3. 之后执行函数async1,首先打印出async1 start
  4. 遇到await,执行async2,打印出async2,并阻断后面代码的执行,将后面的代码加入到微任务队列;
  5. 然后跳出async1async2,遇到Promise,打印出promise1
  6. 遇到resolve,将其加入到微任务队列,然后执行后面的script代码,打印出script end
  7. 之后就该执行微任务队列了,首先打印出async1 end,然后打印出promise2
  8. 执行完微任务队列,就开始执行宏任务队列中的定时器,打印出setTimeout

23:考察点:综合考察

async function async1 () {
  await async2();
  console.log('async1');
  return 'async1 success'
}
async function async2 () {
  return new Promise((resolve, reject) => {
    console.log('async2')
    reject('error')
  })
}
async1().then(res => console.log(res))

输出结果:

async2
Uncaught (in promise) error

代码一旦报错,后面的代码都不在执行.
所以如果想要不影响后面代码的执行.可以在报错出添加catch.

async function async1 () {
  await Promise.reject('error!!!').catch(e => console.log(e))
  console.log('async1');
  return Promise.resolve('async1 success')
}
async1().then(res => console.log(res))
console.log('script start')

就能正常输出了.

script start
error!!!
async1
async1 success

24.考察点:resolve执行后下面的代码也会继续执行.

const first = () => (new Promise((resolve, reject) => {
    console.log(3);
    let p = new Promise((resolve, reject) => {
        console.log(7);
        setTimeout(() => {
            console.log(5);
            resolve(6);
            console.log(p)
        }, 0)
        resolve(1);
    });
    resolve(2);
    p.then((arg) => {
        console.log(arg);
    });
}));
first().then((arg) => {
    console.log(arg);
});
console.log(4);

输出结果:

3
7
4
1
2
5
Promise{<resolved>: 1}

执行过程:

  1. 首先会进入Promise,打印出3,之后进入下面的Promise,打印出7;
  2. 遇到了定时器,将其加入宏任务队列;
  3. 执行Promise p中的resolve,状态变为resolved,返回值为1;
  4. 执行Promise first中的resolve,状态变为resolved,返回值为2;
  5. 遇到p.then,将其加入微任务队列,遇到first().then,将其加入任务队列;
  6. 执行外面的代码,打印出4;
  7. 这样第一轮宏任务就执行完了,开始执行微任务队列中的任务,先后打印出1和2;
  8. 这样微任务就执行完了,开始执行下一轮宏任务,宏任务队列中有一个定时器,执行它,打印出5,由于执行已经变为resolved状态,所以resolve(6)不会再执行;
  9. 最后console.log(p)打印出Promise{<resolved>: 1}

关于为什么 1 比 2 先执行 ?

1.resovle(1)执行修改p的状态为resolved,触发 p的微任务回调.但是这个时候,p的回调队列还是空的.
2.执行resolve,修改first的状态为resolved.触发resolve的的微任务回调队列.这个时候它也是空的.所以它这里就没有添加到上微任务.因为它的代码还没有执行完毕,它的同步代码执行完毕之后,属于它的first().then()才能添加进去.
3.执行p.then.为p添加微任务回调,发现它的内部已经是resolved,直接执行添加微任务回调.
4.接着是first.then的微任务回调

这里的关键点是 resolve(2)的执行虽然改变了first的内部状态和结果,但是轮到它的then 执行,还需要它内部肚子里的p.then执行完毕之后才能轮到执行.

25.考察点:综合考察

const async1 = async () => {
  console.log('async1');
  setTimeout(() => {
    console.log('timer1')
  }, 2000)
  await new Promise(resolve => {
    console.log('promise1')
  })
  console.log('async1 end')
  return 'async1 success'
} 
console.log('script start');
async1().then(res => console.log(res));
console.log('script end');
Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .catch(4)
  .then(res => console.log(res))
setTimeout(() => {
  console.log('timer2')
}, 1000)

输出结果:

script start
async1
promise1
script end
1
timer2
timer1

这道题的考察点有两个:

  • await 后面的Promise 状态并没有改变,所以造成后面的代码都不会执行
  • 值穿透 Promise.resolve(1)的值 在后面传递的时候,后面的回调如果不是函数,都将是无效的.

26.考察点:综合考察

const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve('resolve3');
    console.log('timer1')
  }, 0)
  resolve('resovle1');
  resolve('resolve2');
}).then(res => {
  console.log(res)  
  setTimeout(() => {
    console.log(p1)
  }, 1000)
}).finally(res => {
  console.log('finally', res)
})

输出结果:

resovle1
finally undefined
timer1
Promise{<resolved>: undefined}

考察点:

  1. finally 的回调并没有参数,同时它是then的特例,同样会加入微任务队列中
  2. Promise的状态只能改变一次

27.考察点: node

console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

输出结果:

1
7
6
8
2
4
3
5
9
11
10
12

考察点:

process.nextTick当做微任务执行就可以了.
宏任务中的微任务,只和自己有关,两个宏任务中的微任务,并不会搅合,不需要考虑那么多.

28.考察点:综合考察

console.log(1)

setTimeout(() => {
  console.log(2)
})

new Promise(resolve =>  {
  console.log(3)
  resolve(4)
}).then(d => console.log(d))

setTimeout(() => {
  console.log(5)
  new Promise(resolve =>  {
    resolve(6)
  }).then(d => console.log(d))
})

setTimeout(() => {
  console.log(7)
})

console.log(8)

输出结果:

1
3
8
4
2
5
6
7

这道题相对于上一道反而简单.

29.考察点:综合考察

console.log(1);
    
setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => {
    console.log(3)
  });
});

new Promise((resolve, reject) => {
  console.log(4)
  resolve(5)
}).then((data) => {
  console.log(data);
})

setTimeout(() => {
  console.log(6);
})

console.log(7);

输出结果:

1
4
7
5
2
3
6

考察点:
宏任务和微任务的关系
Promise.resolve().then()添加一个微任务.

30.考察点:综合考察

Promise.resolve().then(() => {
    console.log('1');
    throw 'Error';
}).then(() => {
    console.log('2');
}).catch(() => {
    console.log('3');
    throw 'Error';
}).then(() => {
    console.log('4');
}).catch(() => {
    console.log('5');
}).then(() => {
    console.log('6');
});

输出结果:

1
3
5
6

在这道题目中,我们需要知道,无论是thne还是catch中,只要throw 抛出了错误,就会被catch捕获,如果没有throw出错误,就被继续执行后面的then。

31.考察点:

setTimeout(function () {
  console.log(1);
}, 100);

new Promise(function (resolve) {
  console.log(2);
  resolve();
  console.log(3);
}).then(function () {
  console.log(4);
  new Promise((resove, reject) => {
    console.log(5);
    setTimeout(() =>  {
      console.log(6);
    }, 10);
  })
});
console.log(7);
console.log(8);

输出结果:


2
3
7
8
4
5
6
1

考察点:
这里的疑惑点就是resolve执行的时候,虽然会改变Promsie对象的状态和值,同时触发它的回调.
但是这里它的回调还没有,因为它是同步执行的,后面then的代码还没有来得及执行.

所以需要它的同步代码全都执行完毕,才能执行后面的then方法来添加回调函数.

32.考察Promise

Promise.resolve(1).then(()=>{
    console.log(1)
}).then(()=>{
    console.log(2)
}).then(()=>{
    console.log(3)
}).then(()=>{
    console.log(4)
})

Promise.resolve(1).then(()=>{
    console.log(5)
}).then(()=>{
    console.log(6)
}).then(()=>{
    console.log(7)
}).then(()=>{
    console.log(8)
})

输出结果:

1
5
2
6
3
7
4
8

这道题的重点是:Promise.then它的方法是放入微任务队列执行的.
所以两个代码就是依次放入微任务队列.变成了交替打印的效果.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345