前端入门11 -- JavaScript之Promise

回调函数

  • 回调函数分为两种类型,分别为同步回调与异步回调;
  • 同步回调:会立即执行,完全执行完了才结束,不会放入回调队列中;
  • 异步回调:不会立即执行,会放入回调队列中 将来执行;
  <script>

    //同步回调
    const arr = [1, 3, 5];
    arr.forEach((item) => {
      console.log(item);
    });
    console.log('forEach(之后)');

    //异步回调
    setTimeout(() => {
      console.log('异步回调');
    }, 0);
    console.log('setTimeout()之后');

  </script>
  • 遍历回调属于同步回调,立即执行;
  • 定时器中的回调属于异步回调,不会立即执行;

常见的内置错误

  • Error:所有错误的父类型;
  • ReferenceError:引用变量不存在;
  • TypeError:数据类型不正确;
  • RangeError:数据值不在其所允许的范围之内;
  • SyntaxError:语法错误;
  <script>
    //1.ReferenceError:引用变量不存在
    console.log(a); //ReferenceError: a is not defined

    //2.TypeError:数据类型不正确
    let b = {};
    b.xxx(); //TypeError: b.xxx is not a function

    //3.RangeError:数据值不在其所允许的范围之内
    function func() {
      func()
    }
    func(); //RangeError: Maximum call stack size exceeded

    //4.SyntaxError:语法错误
    const c = """"; //SyntaxError: Unexpected string
  </script>
错误的处理
  • 错误处理的方式有两种:捕获错误和抛出错误;
  • 捕获错误:try ... catch
<script>

    try {
      let b;
      console.log(b.xxx);
    } catch (error) {
      console.log(error.message);
      console.log(error.stack);
    }
    console.log('出错之后');

  </script>
  • 抛出错误:throw error,错误由调用者进行处理;
  <script>

    function something() {
      if (Date.now % 2 === 1) {
        console.log('当前时间为奇数,可以执行任务');
      } else {
        throw new Error('当前时间为偶数,抛出异常 无法执行任务');
      }
    }

    //抛出错误之后 调用者来处理了
    try {
      something();
    } catch (error) {
      alert(error.message);
    }

  </script>

Promise

  • Promise是JS中进行异步编程的一种解决方案;
  • 从语法上来说,Promise是一个构造函数;
  • 从功能上来说,Promise对象用来封装一个异步操作并可以获取其结果;
Promise的状态
  • 初始化状态为pending;
    • pending变为resolved;
    • pending变为reiected;
  • 一个Promise对象,其状态只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason;
  • Promise执行的基本流程如下:
image.png
Promise的基本使用
  • 首先创建Promise实例对象;
  • 在执行器中执行异步任务;
  • 获取异步任务的处理结果;
  <script>
    //1.创建Promise实例对象
    const promise = new Promise((resolve, reject) => {
      //2.在执行器中 执行异步任务
      setTimeout(() => {
        const time = Date.now();
        if (time % 2 === 0) {
          resolve('成功的数据,time = ' + time);
        } else {
          reject('失败的数据,time = ' + time);
        }
      })
    }, 1000);

    //3.处理异步任务的结果
    promise.then(
      value => {
        console.log('成功的回调', value);
      },
      reason => {
        console.log('失败的回调', reason);
      }
    )
  </script>
Promise的优点
  • 首先Promise指定回调函数的方式更加灵活;
    • 纯回调函数形式,指定回调函数必须在异步任务执行之前;
    • Promise形式,指定回调函数在执行异步任务前后均可以,更加灵活;
  • 其次Promise支持链式调用,可以解决回调地狱问题,终极解决方案为:async/await;
  <script>
    //1.使用纯回调函数的形式
    function successCallback(result) {
      console.log('成功结果:' + result);
    }
    function failCallback(error) {
      console.log('失败原因:' + error);
    }

    //必须在异步任务执行之前 指定回调函数
    createAudioFileAsync(audioSettings, successCallback, failCallback);

    //2.使用Promise的形式
    const promise = createAudioFileAsync(audioSettings);
    //指定回调函数 非常灵活 可以在异步任务执行前后 指定均可以
    promise.then(successCallback, failCallback);

  </script>
  <script>

    function failCallback(error) {
      console.log('失败原因:' + error);
    }

    //案例:三个请求 依次依赖
    //1.回调嵌套地狱 下一层函数的调用 依赖上一层函数的结果
    doFirstThing(function (result) {
      doSecondThing(result, function (newResult) {
        doThirdThing(newResult, function (lastResult) {
          console.log('lastResult =', lastResult);
        }, failCallback);
      }, failCallback);
    }, failCallback);

    //2.使用Promise链式调用 解决回调地狱问题
    doFirstThing()
      .then(function (result) {
        return doSecondThing(result);
      })
      .then(function (newResult) {
        return doThirdThing(newResult);
      })
      .then(function (lastResult) {
        console.log('lastResult =', lastResult);
      })
      .catch(failCallback);

      //3.回调地狱的终极解决方案: async/await 
      async function request() {
        try {
          const result = await doFirstThing();
          const newResult = await doSecondThing(result);
          const lastResult = await doThirdThing(newResult);
          console.log('lastResult =', lastResult);
        } catch (error) {
          failCallback(error);
        }
      }

  </script>
Promise常见API
image.png
  <script>

    //then value   -->   异步执行成功
    //catch reason --> 异步执行失败
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('111111');
      }, 5000);
    }).then((value) => {
      console.log(value);
    }).catch((reason) => {
      console.log(reason);
    });

    //Promise.resolve() 或者 Promise.reject() 均会返回一个Promise实例对象
    const p1 = new Promise((resolve, reject) => {
      resolve(1);
    });
    const p2 = Promise.resolve(2);
    const p3 = Promise.reject(3);

    p1.then(value => console.log(value));
    p2.then(value => console.log(value));
    p3.catch(reason => console.log(reason));

    //pAll 数组中异步操作只要有一个失败 就直接失败
    const pAll = Promise.all([p1, p2, p3]);
    pAll.then(
      value => {
        console.log('all onResolve()', value);
      },
      reason => {
        console.log('all onReject()', reason);
      }
    )

    //异步操作数组中的  某个异步操作最先返回结果 就是pRace的最终结果
    const pRace = Promise.race([p1, p2, p3]);
    pRace.then(
      value => {
        console.log('all onResolve()', value);
      },
      reason => {
        console.log('all onReject()', reason);
      }
    )
    
  </script>
  • Promise.resolve(value):返回值为一个新的promise,参数value值可以是promise,可以是非promise
    • 当value为非promise时,那么新promise的状态结果为resolve成功;
    • 当value为promise时,那么新promise的状态结果为value的状态结果;
  • Promise.reject(value):返回值为一个新的promise,其状态结果为reject失败;
  • Promise.all(promise数组):返回值为一个新的promise,其状态结果为:
    • 当promise数组中存在一个状态失败的,那么新promise的状态结果为失败;
    • 当promise数组中都成功,那么新promise的状态结果为一个数组集合值;
  • Promise.race(promise数组):返回值为一个新的promise,其状态结果为:promise数组中先返回状态结果的promise的状态结果;

Promise的使用注意事项

  • promise的状态改变分为三种情况:
    • 执行成功resolve(value),pending --> resolve;
    • 执行失败reject(reason),pending --> reject;
    • 抛出异常 throw error,pending --> reject;
  • 一个promise对象,可以指定多个状态回调,且多个状态回调都会执行;
  <script>

    const p = new Promise((resolve, reject) => {
      // resolve(1); //成功  pending --> resolve
      // reject(2);  //失败  pending --> reject
      throw new Error('报错了'); //抛出异常 pending --> reject
    });
    //promise指定多个回调 都会调用
    p.then(
      value => { },
      reason => { console.log('reason', reason) }
    );
    p.then(
      value => { },
      reason => { console.log('reason', reason) }
    );
  </script>
  • 如何控制改变promise状态指定回调函数的先后顺序?
    • 常规情况下:先指定回调函数,再改变promise状态,执行回调函数;
  <script>

    //先指定回调函数 再改变状态
    new Promise((resolve, reject) => {
      //2.异步执行 再改变状态(同时指定数据) 异步执行下面指定的回调函数
      setTimeout(() => {
        resolve(1);
      })
    }).then(
      //1.先指定回调函数,promise会保存当前指定的回调函数
      value => { console.log('value', value) },
      reason => { console.log('reason', reason) }
    );

    //先指定回调函数 再改变状态
    new Promise((resolve, reject) => {
      //1.先改变状态(同时指定数据)
      resolve(1);
    }).then(
      //2.后指定回调函数 异步执行回调函数
      value => { console.log('value', value) },
      reason => { console.log('reason', reason) }
    );

    //先指定回调函数 再改变状态
    const p = new Promise((resolve, reject) => {
      //2.异步执行 再改变状态(同时指定数据) 异步执行下面指定的回调函数
      setTimeout(() => {
        resolve(1);
      })
    });

    setTimeout(() => {
      p.then(
        //1.先指定回调函数,promise会保存当前指定的回调函数
        value => { console.log('value', value) },
        reason => { console.log('reason', reason) }
      );
    }, 2000);

  </script>
  • promise.then()会返回一个新的promise对象,此promise的状态结果由什么决定?
    • 由then()指定的回调函数执行的结果决定;
    • then()指定的回调函数,没有返回值,则新的promise对象状态变成resolve,value值为undefined;
    • then()指定的回调函数,返回非promise的任意值value,则新的promise对象状态变成resolve,会执行成功的回调,且获取value值;
    • then()指定的回调函数,抛出异常,则新的promise对象状态变成reject,会执行失败的回调;
    • then()指定的回调函数,返回另一个新的promise,则此promise的状态结果会成为新promise的状态结果;
  <script>

    new Promise((resolve, reject) => {
      resolve(1);
    }).then(
      value => { console.log('onResolved1', value) },
      reason => { 
        console.log('onRejected1', reason) 
        // return 2;
        // return Promise.resolve(3);
        // return Promise.reject(4);
        // throw 5;
      }
    ).then(
      value => { console.log('onResolved2', value) },
      reason => { console.log('onRejected2', reason) }
    );

  </script>
  • promise如何串联多个操作任务?
    • promise.then()可返回一个新的promise;
    • promise.then()的链式调用可串联多个同步/异步任务;
  <script>

    new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('执行异步任务1');
        resolve(1);
      }, 1000);
    }).then(
      value => {
        console.log('异步任务1的结果:', value);
        console.log('执行同步任务2');
        return 2;
      },
      reason => {
        console.log('onRejected1', reason);
      }
    ).then(
      value => {
        console.log('同步任务2的结果:', value);
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            console.log('执行异步任务3');
            resolve(3);
          }, 1000);
        })
      },
      reason => {
        console.log('onRejected2', reason);
      }
    ).then(
      value => {
        console.log('异步任务3的结果:', value);
      }
    );

  </script>
image.png
  • promise的异常传透:
    • 当使用promise的then链式调用时,可以再最后指定失败的回调;
    • 前面任何操作出现了异常,都会传到最后失败的回调;
  <script>

    new Promise((resolve, reject) => {
      reject(1);
    }).then(
      value => {
        console.log('onResolve1:', value);
        return 2;
      },
      // reason => {
      //   throw reason;
      // }
    ).then(
      value => {
        console.log('onResolve2:', value);
        return 3;
      },
      // reason => {
      //   throw reason;
      // }
    ).then(
      value => {
        console.log('onResolve3:', value);
      },
      // reason => {
      //   throw reason;
      // }
    ).catch(
      reason => {
        console.log('onReject: ', reason);
      }
    )

  </script>
  • . catch失败处理,上面没有失败的处理,就会执行. catch中的代码,没有失败的处理等价于reason => { throw reason },抛出了异常,然后一直往下传递异常,最终会执行. catch中的代码;
  • 如何中断promise链?
    • 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数;
    • 方案:在回调函数中返回一个pending状态的promise对象;
  <script>

    new Promise((resolve, reject) => {
      reject(1);
    }).then(
      value => {
        console.log('onResolve1:', value);
        return 2;
      },
    ).then(
      value => {
        console.log('onResolve2:', value);
        return 3;
      },
    ).then(
      value => {
        console.log('onResolve3:', value);
      },
    ).catch(
      reason => {
        console.log('onReject1: ', reason);
        // throw reason;
        // return Promise.reject(3);
        //返回一个pending状态的promise
        //下面的回调函数不会执行
        return new Promise(() => { });
      }
    ).then(
      value => {
        console.log('onResolve3:', value);
      },
      reason => {
        console.log('onReject2: ', reason);
      }
    )

  </script>
  • 注意.catch()函数也会返回一个新的promise对象;

自定义Promise

  • 函数对象,代码如下:
//自定义Promise函数模块
(function (window) {

  const PENDING = 'pending';
  const RESOLVED = 'resolved';
  const REJECTED = 'rejected';

  //Promise的构造函数
  function Promise(excutor) {
    const self = this;
    //promise状态 初始化为pending
    self.status = PENDING;
    //promise异步操作的结果数据
    self.data = undefined;
    //promise的回调函数
    self.callbacks = [];

    function resolve(value) {
      if (self.status !== PENDING) {
        return;
      }
      //将状态改成resolved
      self.status = RESOLVED;
      self.data = value;
      //若存在callback回调函数,则立即异步执行回调函数
      if (self.callbacks.length > 0) {
        setTimeout(() => {
          self.callbacks.forEach(element => {
            element.onResolved(value);
          });
        });
      }
    }

    function reject(reason) {
      if (self.status !== PENDING) {
        return;
      }
      self.status = REJECTED;
      self.data = reason;
      if (self.callbacks.length > 0) {
        setTimeout(() => {
          self.callbacks.forEach(element => {
            element.onRejected(reason);
          });
        });
      }
    }

    try {
      excutor(resolve, reject);
    } catch (error) {
      //捕获异常了 执行reject方法 状态成为rejected
      reject(error);
    }
  }

  //Promise原型上的函数方法
  Promise.prototype.then = function (onResolved, onRejected) {
    //当前promise对象
    const self = this;

    onResolved = typeof onResolved === 'function' ? onResolved : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };

    //返回一个新的promise对象
    return new Promise((resolve, reject) => {
      //处理函数
      function handle(callback) {
        //新promise对象的状态结果 由当前promise对象的状态结果决定
        //1.当前promise结果为抛出异常,则新的promise结果为失败,值为异常error
        //2.当前promise结果为非promise,则新的promise结果为成功,值为异常value
        //3.当前promise结果为promise,则新的promise结果为promise的结果
        try {
          const result = callback(self.data);
          if (result instanceof Promise) {
            result.then(resolve, reject);
          } else {
            resolve(result);
          }
        } catch (error) {
          reject(error);
        }
      }

      if (this.status === RESOLVED) {
        //立即异步执行 当前promise对象 成功的回调函数
        setTimeout(() => {
          handle(onResolved);
        });
      } else if (self.status === REJECTED) {
        setTimeout(() => {
          handle(onRejected);
        });
      } else {
        //将成功和失败的回调函数保存到callbacks容器中
        self.callbacks.push({
          onResolved(value) {
            handle(onResolved);
          },
          onRejected(reason) {
            handle(onRejected);
          }
        });
      }
    });

    if (self.status === PENDING) {
      //保存回调方法 到一个对象中
      self.callbacks.push({
        onResolved,
        onRejected
      })
    } else if (self.status === RESOLVED) {
      setTimeout(() => {
        resolve(self.data)
      });
    } else {
      setTimeout(() => {
        reject(self.data);
      });
    }

  }

  Promise.prototype.catch = function (onRejected) {
    Promise.prototype.then(undefined, onRejected);
  }

  //Promise函数对象方法
  Promise.resolve = function (value) {
    //返回一个状态结果为 成功或失败的promise对象
    return new Promise((resolve, reject) => {
      if (value instanceof Promise) {
        value.then(resolve, reject);
      } else {
        resolve(value);
      }
    })
  }

  Promise.reject = function (reason) {
    //返回一个状态结果为失败的promise对象
    return new Promise((resolve, reject) => {
      reject(reason);
    })
  }

  Promise.all = function (promises) {
    //保存所有成功的value的数组
    const values = new Array(promises.length);
    //记录成功promise的数量
    let resloveCount = 0;
    return new Promise((reslove, reject) => {
      promises.forEach((p, index) => {
        p.then(
          value => {
            resloveCount++;
            values[index] = value;
            if (resloveCount === promises.length) {
              reslove(values);
            }
          },
          reason => {
            reject(reason);
          }
        )
      });
    });
  }

  Promise.race = function (promises) {
    return new Promise((resove, reject) => {
      promises.forEach((p, index) => {
        p.then(
          value => {
            resove(value);
          },
          reason => {
            reject(reason);
          }
        )
      });
    });
  }

  //向外暴露Promise的构造函数
  window.Promise = Promise;
})(window)
  • 类Class对象,代码如下:
//自定义Promise函数模块
(function (window) {

  const PENDING = 'pending';
  const RESOLVED = 'resolved';
  const REJECTED = 'rejected';

  class Promise {
    constructor(excutor) {
      //Promise的构造函数
      const self = this;
      //promise状态 初始化为pending
      self.status = PENDING;
      //promise异步操作的结果数据
      self.data = undefined;
      //promise的回调函数
      self.callbacks = [];

      function resolve(value) {
        if (self.status !== PENDING) {
          return;
        }
        //将状态改成resolved
        self.status = RESOLVED;
        self.data = value;
        //若存在callback回调函数,则立即异步执行回调函数
        if (self.callbacks.length > 0) {
          setTimeout(() => {
            self.callbacks.forEach(element => {
              element.onResolved(value);
            });
          });
        }
      }

      function reject(reason) {
        if (self.status !== PENDING) {
          return;
        }
        self.status = REJECTED;
        self.data = reason;
        if (self.callbacks.length > 0) {
          setTimeout(() => {
            self.callbacks.forEach(element => {
              element.onRejected(reason);
            });
          });
        }
      }

      try {
        excutor(resolve, reject);
      } catch (error) {
        //捕获异常了 执行reject方法 状态成为rejected
        reject(error);
      }
    }
    //Promise原型上的函数方法
    then(onResolved, onRejected) {
      //当前promise对象
      const self = this;

      onResolved = typeof onResolved === 'function' ? onResolved : value => value;
      onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };

      //返回一个新的promise对象
      return new Promise((resolve, reject) => {
        //处理函数
        function handle(callback) {
          //新promise对象的状态结果 由当前promise对象的状态结果决定
          //1.当前promise结果为抛出异常,则新的promise结果为失败,值为异常error
          //2.当前promise结果为非promise,则新的promise结果为成功,值为异常value
          //3.当前promise结果为promise,则新的promise结果为promise的结果
          try {
            const result = callback(self.data);
            if (result instanceof Promise) {
              result.then(resolve, reject);
            } else {
              resolve(result);
            }
          } catch (error) {
            reject(error);
          }
        }

        if (this.status === RESOLVED) {
          //立即异步执行 当前promise对象 成功的回调函数
          setTimeout(() => {
            handle(onResolved);
          });
        } else if (self.status === REJECTED) {
          setTimeout(() => {
            handle(onRejected);
          });
        } else {
          //将成功和失败的回调函数保存到callbacks容器中
          self.callbacks.push({
            onResolved(value) {
              handle(onResolved);
            },
            onRejected(reason) {
              handle(onRejected);
            }
          });
        }
      });

      if (self.status === PENDING) {
        //保存回调方法 到一个对象中
        self.callbacks.push({
          onResolved,
          onRejected
        })
      } else if (self.status === RESOLVED) {
        setTimeout(() => {
          resolve(self.data)
        });
      } else {
        setTimeout(() => {
          reject(self.data);
        });
      }

    }

    catch(onRejected) {
      Promise.prototype.then(undefined, onRejected);
    }

    //Promise函数对象方法
    static resolve(value) {
      //返回一个状态结果为 成功或失败的promise对象
      return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
          value.then(resolve, reject);
        } else {
          resolve(value);
        }
      })
    }

    static reject(reason) {
      //返回一个状态结果为失败的promise对象
      return new Promise((resolve, reject) => {
        reject(reason);
      })
    }

    static all(promises) {
      //保存所有成功的value的数组
      const values = new Array(promises.length);
      //记录成功promise的数量
      let resloveCount = 0;
      return new Promise((reslove, reject) => {
        promises.forEach((p, index) => {
          p.then(
            value => {
              resloveCount++;
              values[index] = value;
              if (resloveCount === promises.length) {
                reslove(values);
              }
            },
            reason => {
              reject(reason);
            }
          )
        });
      });
    }

    static race(promises) {
      return new Promise((resove, reject) => {
        promises.forEach((p, index) => {
          p.then(
            value => {
              resove(value);
            },
            reason => {
              reject(reason);
            }
          )
        });
      });
    }
  }
  //向外暴露Promise的构造函数
  window.Promise = Promise;
}
)(window)

async与await

  • async 函数:函数的返回值是promise对象,promise对象的状态结果由async函数执行的返回值决定;
  <script>

    async function test() {
      // return 1;
      throw 2;
      // return Promise.resolve(3);
    }

    //返回结果为promise对象
    const result = test();
    result.then(
      value => {
        console.log('onResolved()',value);
      },
      reason => {
        console.log('onRejected()',reason);
      }
    );

  </script>
  • await 表达式:一般情况下await右侧的表达式为promise对象,也可以是其他的值;‘
    • 若表达式是promise对象,await返回的是promise成功的值;
    • 若表达式是其他值,直接将此值作为await的返回值;
  • 注意事项:
    • await必须写在async函数中,但async函数中可以没有await;
    • 如果await的promise失败了,就会抛出异常,需要通过try...catch来捕获处理;
  <script>

    function test2() {
      return new Promise((reslove, reject) => {
        setTimeout(() => {
          // reslove(5);
          reject(6);
        }, 1000);
      })
    }

    async function test3() {
      try {
        //表达式是promise对象,await返回的是promise成功的值
        const value = await test2();
        console.log(value);
      } catch (error) {
        //await的promise失败了,就会抛出异常,需要通过try...catch来捕获处理
        console.log('得到失败的结果', error);
      }

      //表达式是其他值,直接将此值作为await的返回值
      const value = test4();
      console.log(value);
    }

    function test4() {
      return 6;
    }

    test3();

  </script>

异步执行的宏队列与微队列

  • 在JS中 存储 待执行回调函数的 队列 有两种特定的队列,分别为宏队列和微队列;
  • 宏队列:用来保存待执行的宏任务回调函数,例如定时器回调,DOM事件回调,ajax回调;
  • 微队列:用来保存待执行的微任务回调函数,例如Promise回调,MutationObserver回调;
  • JS执行时会区分 这两个队列;
    • JS引擎首先必须先执行完所有的初始化同步任务代码;
    • 每次准备取出第一个宏任务执行前,都要将所有微任务一个一个取出来执行
  <script>

    setTimeout(() => {
      //回调函数 放入宏队列
      console.log('timeout callback1()');
      Promise.resolve(3).then(
        value => {
          //回调函数 放入微队列
          console.log('Promise onResolved3()', value);
        }
      )
    }, 0);

    setTimeout(() => {
      //回调函数 放入宏队列
      console.log('timeout callback2()');
    }, 0);

    Promise.resolve(1).then(
      value => {
        //回调函数 放入微队列
        console.log('Promise onResolved1()', value);
      }
    )
    Promise.resolve(2).then(
      value => {
        //回调函数 放入微队列
        console.log('Promise onResolved2()', value);
      }
    )

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

推荐阅读更多精彩内容