JS新特性(二)

JS是单线程的

  • 1.JS是单线程的

    • 所以JS中的代码都是串行的,前面没有执行完毕后面不能执行
  • 2.JS分为同步代码和异步代码

    • 除了"事件绑定的函数"和"回调函数"以外的都是同步代码
    • 2.1程序运行会从上至下依次执行所有的同步代码
    • 2.2在执行的过程中如果遇到异步代码会将异步代码放到事件循环中
    • 2.3当所有同步代码都执行完毕后,JS会不断检测事件循环中的异步代码是否满足条件
    • 2.4一旦满足条件就执行满足条件的异步代码
    • 这也就是为什么有时输出的顺序跟编写代码的顺序不一致的原因
  • 3.为什么JS是单线程的?

    • javaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。
    • 这决定了它只能是单线程,否则会带来很复杂的同步问题。

例如:
如果JS是多线程的,现在有一个线程要修改元素中的内容, 一个线程要删除该元素,这时浏览器应该以哪个线程为准?


promise基本概念

  • 1.什么是promise?

    • promise是ES6中新增的异步编程解决方案, 在代码中的表现是一个对象
  • 示例需求: 从网络上加载3个资源,要求加载完资源1才能加载资源2, 加载完资源2才能加载资源3
    前面任何一个资源加载失败, 后续资源都不加载

以前的解决方案(层层嵌套):
function request(fn) {
        setTimeout(function () {
            fn("拿到的数据");
        }, 1000);
    }
request(function (data) {
    console.log(data, 1);
    request(function (data) {
        console.log(data, 2);
        request(function (data) {
            console.log(data, 3);
        });
    });
});
  • 2.promise作用
    • 企业开发中为了保存异步代码的执行顺序, 那么就会出现回调函数层层嵌套
    • 如果回调函数嵌套的层数太多,就会导致代码的阅读性, 可维护性大大降低
    • promise对象可以将异步操作以同步流程来表示, 避免了回调函数层层嵌套(回调地狱)
不用层层嵌套函数,可以这样解决:
function request() {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve("拿到的数据");
        }, 1000);
    });
}
request().then(function (data) {
    console.log(data, 1);
    return request();
}).then(function (data) {
    console.log(data, 2);
    return request();
}).then(function (data) {
    console.log(data, 3);
});

promise基本使用

  • 1.什么是Promise?

    • Promise是ES6中新增的一个对象,通过Promise就可以实现 用同步的流程来表示异步的操作
    • 通过Promise就可以避免回调函数层层嵌套(回调地狱)问题
  • 2.如何创建Promise对象?

    • 格式:new Promise(function(resolve, reject){});
    • promise对象不是异步的,只要创建promise对象就会立即执行存放的代码
  • 3.Promise是如何实现通过同步的流程来表示异步的操作的?

    • promise对象是通过状态的改变来实现的, 只要状态发生改变就会自动触发对应的函数
  • 4.Promise对象三种状态

    • pending:默认状态,只要没有告诉promise任务是成功还是失败就是pending状态
    • fulfilled(resolved):只要调用resolve函数, 状态就会变为fulfilled, 表示操作成功
    • rejected:只要调用rejected函数,状态就会变为rejected, 表示操作失败

注意点:
状态一旦改变既不可逆,既从pending变为fulfilled, 那么永远都是fulfilled
既从pending变为rejected,那么永远都是rejected

  • 5.监听Promise状态改变
    • 我们还可以通过函数来监听状态的变化
      • resolved --> then()
      • rejected --> catch()

then方法

  • then方法
    • then方法接收两个参数,第一个参数是状态切换为成功时的回调,第二个参数是状态切换为失败时的回调
let promise = new Promise(function (resolve, reject) {
    // resolve(); // 将状态修改为成功
    reject(); // 将状态修改为失败
});
promise.then(function () {
    console.log("成功");
}, function () {
    console.log("失败");
});
  • 1.then方法
    • 在修改promise状态时,可以传递参数给then方法中的回调函数
// resolve = success, reject = error;
let promise = new Promise(function (resolve, reject) {
    // resolve("111"); //  success("111");
    reject("aaa"); //   error("aaa");
});

/*promise.then(function (data) {
    console.log("成功", data);
}, function (data) {
    console.log("失败", data);
}); */
function success(data) {
    console.log(data);
}
function error(data) {
    console.log(data);
}
promise.then(success, error);    //  aaa
  • 2.then方法
    • 同一个promise对象可以多次调用then方法,当该promise对象的状态改变时所有then方法都会被执行
let promise = new Promise(function (resolve, reject) {
    // resolve();
    reject(); 
});
promise.then(function () {
    console.log("成功1");
}, function () {
    console.log("失败1");      // 失败1
});
promise.then(function () {
    console.log("成功2");
}, function () {
    console.log("失败2");      // 失败2
});
  • 3.then方法
    • then方法每次执行完毕后会返回一个新的promise对象
let promise = new Promise(function (resolve, reject) {
    resolve(); 
    // reject();
});
let p2 = promise.then(function () {
    console.log("成功1");     // 成功1
}, function () {
    console.log("失败1");
});
console.log(p2);     //  打印p2的promise对象
console.log(promise === p2);    // false
  • 4.then方法
    • 可以通过上一个promise对象的then方法给下一个promise对象的then方法传递参数
let promise = new Promise(function (resolve, reject) {
    // resolve("111"); 
    reject("aaa"); 
});
let p2 = promise.then(function (data) {
    console.log("成功1", data);
    return "222";
}, function (data) {
    console.log("失败1", data);    // 失败1 aaa
    return "bbb";
});
p2.then(function (data) {
    console.log("成功2", data);   // 成功2 bbb
}, function (data) {
    console.log("失败2", data);     
});

注意点:
无论是在上一个promise对象成功的回调还是失败的回调传递的参数,
都会传递给下一个promise对象成功的回调

  • 5.then方法
    • 如果then方法返回的是一个Promise对象,那么会将返回的Promise对象的执行结果中的值传递给下一个then方法
let promise = new Promise(function (resolve, reject) {
    resolve("111"); 
    // reject("aaa"); 
});
let ppp = new Promise(function (resolve, reject) {
    // resolve("222"); 
    reject("bbb"); 
});
let p2 = promise.then(function (data) {
    console.log("成功1", data);   // 成功1 111
    return ppp;
}, function (data) {
    console.log("失败1", data);
    return "bbb";
});
p2.then(function (data) {
    console.log("成功2", data);
}, function (data) {
    console.log("失败2", data);   // 失败2 bbb
});

catch方法

  • 1.catch方法
    • catch 其实是 then(undefined, () => {}) 的语法糖
    • 只有then失败才会执行,不监听成功
    • catch只有一个参数
let promise = new Promise(function (resolve, reject) {
    // resolve(); // 将状态修改为成功,不输出
    reject(); // 将状态修改为失败  才输出
});
promise.catch(function () {
    console.log("abc");   //  abc
});
  • 2.catch方法
    • 注意点: 如果需要分开监听,也就是通过then监听成功通过catch监听失败,那么必须使用链式编程, 否则会报错
let promise = new Promise(function (resolve, reject) {
    // resolve(); 
    reject(); 
});

promise.then(function () {
    console.log("成功");
}).catch(function () {    // 监听失败
    console.log("失败");
});


/*  这么写会报错,没用链式编程
promise.then(function () {
    console.log("成功");
});
promise.catch(function () {
    console.log("失败");
});
*/
  • 3.catch方法
    • 不使用链式编程报错的原因是
      • 1.如果promise的状态是失败,但是没有对应失败的监听就会报错
      • 2.then方法会返回一个新的promise,新的promise会继承原有promise的状态(原有的是成功状态,那继承的就是成功状态,反之亦然)
      • 3.如果新的promise状态是失败,但是没有对应失败的监听也会报错
let promise = new Promise(function (resolve, reject) {
    // resolve(); // 将状态修改为成功
    reject(); // 将状态修改为失败
});
let p2 = promise.then(function () {
    console.log("成功");    // 执行完返回的是一个新的promise,并且状态是继承的失败状态
});
console.log(p2);
promise.catch(function () {
    console.log("失败1");
});
p2.catch(function () {    //  监听新的promise失败状态
    console.log("失败2");
});

catch方法特点、与then使用的区别

  • 1.catch方法(同then)
    • 在修改promise状态时,可以传递参数给catch方法中的回到函数
let promise = new Promise(function (resolve, reject) {
    reject("111");
});
promise.catch(function (data) {
    console.log(data);    // 111
});
  • 2.catch方法(同then)
    • 同一个promise对象可以多次调用catch方法,当该promise对象的状态改变时所有catch方法都会被执行
let promise = new Promise(function (resolve, reject) {
    reject();
});
promise.catch(function () {
    console.log("失败1");    // 失败1
});
promise.catch(function () {
    console.log("失败2");   // 失败2
});
promise.catch(function () {
    console.log("失败3");   // 失败3
});
  • 3.catch方法(同then)
    • catch方法每次执行完毕后会返回一个新的promise对象
let promise = new Promise(function (resolve, reject) {
    reject();
});
let p2 = promise.catch(function () {
    console.log("失败1");    //失败1
});
console.log(p2);     // 打印p2的promise对象
console.log(promise === p2);  // false
  • 4.catch方法(同then)
    • 上一个promise对象也可以给下一个promise成功的传递参数
let promise = new Promise(function (resolve, reject) {
    reject();
});
let p2 = promise.catch(function () {
    console.log("失败1");     // 失败1
    return "it666";
});
p2.then(function (data) {
    console.log("成功2", data); // 成功2 it666
}, function (data) {
    console.log("失败2", data);  
});

注意点:
无论是在上一个promise对象成功的回调还是失败的回调传递的参数,都会传递给下一个promise对象成功的回调

  • 5.catch方法(同then)
    • catch方法如果返回的是一个Promise对象,那么会将返回的Promise对象的,执行结果中的值传递给下一个catch方法
let promise = new Promise(function (resolve, reject) {
    reject();
});
let ppp = new Promise(function (resolve, reject) {
    // resolve("1111");
    reject("abcd");
});
let p2 = promise.catch(function () {
    console.log("失败1");    // 失败1
    return ppp;
});
p2.then(function (data) {
    console.log("成功2", data);
}, function (data) {
    console.log("失败2", data);    // 失败2 abcd
});
  • 6.catch方法(==不同于then的地方==)
    • 和then方法第二个参数的区别在于,catch方法可以捕获上一个promise对象then方法中的异常
let promise = new Promise(function (resolve, reject) {
    resolve();
    // reject();  // 输出: 失败 undefined
});
/*
promise.then(function () {
    console.log("成功");    // 成功
    xxx                    // 报错
}, function () {
    console.log("失败");    
});
*/
应这么写:
promise.then(function () {
    console.log("成功");     // 成功
    xxx
}).catch(function (e) {
    console.log("失败", e);    // 失败  并输出报错内容
});

异常处理

  • 1.JS中的异常

    • 简单粗暴就是有错误出现
    • 由于JS是单线程的, 编写的代码都是串行的,所以一旦前面代码出现错误,程序就会被中断, 后续代码就不会被执行
  • 2.JS中的异常处理

    • 2.1自身编写代码问题, --> 手动修复BUG
    • 2.2外界原因问题, --> try{}catch{}
      对于一些可预见的异常,我们可以使用try{}catch{}来处理
  • 3.JS中如何进行异常处理

    • 利用try{}catch{}来处理异常可以保证程序不被中断, 也可以记录错误原因以便于后续优化迭代更新
    • 格式:try {可能遇到的意外的代码}catch(e) {捕获错误的代码块}
console.log("1");   // 1
say();      // 报错,执行暂停,不会执行之后代码
console.log("2");    

想发生错误代码也要执行完代码的话,用try&catch:
console.log("1");   // 1
try {
    say();      
}catch (e) {
    console.log(e);   // 输出try里的错误地方,然后继续执行下面代码
}
console.log("2");    // 2

手撕Promise上

  • 1.Promise特点
    • 1.1创建时必须传入一个函数, 否则会报错
    • 1.2会给传入的函数设置两个回调函数
    • 1.3刚创建的Promise对象状态是pending
    • 1.4状态一旦发生改变就不可再次改变
    • 1.5可以通过then来监听状态的改变
      • 1.5.1如果添加监听时状态已经改变,立即执行监听的回调
      • 1.5.2如果添加监听时状态还未改变,那么状态改变时候再执行监听回到
      • 1.5.3同一个Promise对象可以添加多个then监听,状态改变时所有的监听按照添加顺序执行
<script>
// 定义常量保存对象的状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise{
    constructor(handle){
        // 0.初始化默认的状态
        this.status = PENDING;
        // 定义变量保存传入的参数
        this.value = undefined;
        this.reason = undefined;
        // 定义变量保存监听的函数
        // this.onResolvedCallback = null;
        // this.onRejectedCallback = null;
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        // 1.判断是否传入了一个函数, 如果没有传入就抛出一个异常
        if(!this._isFunction(handle)){
            throw new Error("请传入一个函数");
        }
        // 2.给传入的函数传递形参(传递两个函数)
        // handle();
        handle(this._resolve.bind(this), this._reject.bind(this));

    }
    then(onResolved, onRejected){
        // 1.判断有没有传入成功的回调
        if(this._isFunction(onResolved)){
            // 2.判断当前的状态是否是成功状态
            if(this.status === FULFILLED){
                onResolved(this.value);
            }
        }
        // 1.判断有没有传入失败的回调
        if(this._isFunction(onRejected)){
            // 2.判断当前的状态是否是失败状态
            if(this.status === REJECTED){
                onRejected(this.reason);
            }
        }
        // 2.判断当前的状态是否是默认状态
        if(this.status === PENDING){
            if(this._isFunction(onResolved)){
                // this.onResolvedCallback = onResolved;
                this.onResolvedCallbacks.push(onResolved);
            }
            if(this._isFunction(onRejected)){
                // this.onRejectedCallback = onRejected;
                this.onRejectedCallbacks.push(onRejected);
            }
        }
    }
    _resolve(value){
        // console.log("_resolve");
        // 这里是为了防止重复修改
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
            // this.onResolvedCallback(this.value);
            this.onResolvedCallbacks.forEach(fn => fn(this.value));
        }
    }
    _reject(reason){
        // console.log("_reject");
        if(this.status === PENDING) {
            this.status = REJECTED;
            this.reason = reason;
            // this.onRejectedCallback(this.reason);
            this.onRejectedCallbacks.forEach(fn => fn(this.reason));
        }
    }
    _isFunction(fn){
        return typeof fn === "function";
    }
}
</script>
<script>
// 测试:
let promise = new MyPromise(function (resolve, reject) {
    // console.log(resolve);
    // console.log(reject);
    // resolve("111");
    // reject("aaa");
    setTimeout(function () {
        // resolve("111");
        reject("aaa");
    }, 2000);
});
promise.then(function (data) {
    console.log("成功1", data);
}, function (data) {
    console.log("失败1", data);
});
promise.then(function (data) {
    console.log("成功2", data);
}, function (data) {
    console.log("失败2", data);
});
promise.then(function (data) {
    console.log("成功3", data);
}, function (data) {
    console.log("失败3", data);
});
console.log(promise);
</script>

手撕Promise中

  • 1.Promise特点
    • 1.1then方法每次执行完毕都会返回一个新的Promise对象
    • 1.2上一个Promise对象的then可以给下一个Promise的then传递数据
      • 1.2.1无论上一个是在成功的回调还是失败的回调传递的参数都会传递给下一个成功的回调
      • 1.2.2如果上一个传递的是Promise对象,那么传给下一个的成功还是失败由传递的Promise状态决定

升级版:

<script>
// 定义常量保存对象的状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise{
    constructor(handle){
        // 0.初始化默认的状态
        this.status = PENDING;
        // 定义变量保存传入的参数
        this.value = undefined;
        this.reason = undefined;
        // 定义变量保存监听的函数
        // this.onResolvedCallback = null;
        // this.onRejectedCallback = null;
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        // 1.判断是否传入了一个函数, 如果没有传入就抛出一个异常
        if(!this._isFunction(handle)){
            throw new Error("请传入一个函数");
        }
        // 2.给传入的函数传递形参(传递两个函数)
        // handle();
        handle(this._resolve.bind(this), this._reject.bind(this));
    }

    then(onResolved, onRejected){
        return new MyPromise((nextResolve, nextReject) => {
            // 1.判断有没有传入成功的回调
            if(this._isFunction(onResolved)){
                // 2.判断当前的状态是否是成功状态
                if(this.status === FULFILLED){
                    // 拿到上一个promise成功回调执行的结果
                    let result = onResolved(this.value);
                    // console.log("result", result);
                    // 判断执行的结果是否是一个promise对象
                    if(result instanceof MyPromise){
                        result.then(nextResolve, nextReject);
                    }else{
                        // 将上一个promise成功回调执行的结果传递给下一个promise成功的回调
                        nextResolve(result);
                    }
                }
            }
            // 1.判断有没有传入失败的回调
            if(this._isFunction(onRejected)){
                // 2.判断当前的状态是否是失败状态
                if(this.status === REJECTED){
                    let result = onRejected(this.reason);
                    if(result instanceof MyPromise){
                        result.then(nextResolve, nextReject);
                    }else {
                        nextResolve(result);
                    }
                }
            }
            // 2.判断当前的状态是否是默认状态
            if(this.status === PENDING){
                if(this._isFunction(onResolved)){
                    // this.onResolvedCallback = onResolved;
                    this.onResolvedCallbacks.push(() => {
                        let result = onResolved(this.value);
                        if(result instanceof MyPromise){
                            result.then(nextResolve, nextReject);
                        }else {
                            nextResolve(result);
                        }
                    });
                }
                if(this._isFunction(onRejected)){
                    // this.onRejectedCallback = onRejected;
                    this.onRejectedCallbacks.push(() => {
                        let result = onRejected(this.reason);
                        if(result instanceof MyPromise){
                            result.then(nextResolve, nextReject);
                        }else {
                            nextResolve(result);
                        }
                    });
                }
            }
        });
    }
    _resolve(value){
        // console.log("_resolve");
        // 这里是为了防止重复修改
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
            // this.onResolvedCallback(this.value);
            this.onResolvedCallbacks.forEach(fn => fn(this.value));
        }
    }
    _reject(reason){
        // console.log("_reject");
        if(this.status === PENDING) {
            this.status = REJECTED;
            this.reason = reason;
            // this.onRejectedCallback(this.reason);
            this.onRejectedCallbacks.forEach(fn => fn(this.reason));
        }
    }
    _isFunction(fn){
        return typeof fn === "function";
    }
}
</script>
<script>
// 测试:
let promise = new MyPromise(function (resolve,reject) {
    // resolve("111");
    // reject("aaa");
    setTimeout(function () {
        // resolve("111");
        reject("aaa");
    }, 2000);
});
let ppp = new MyPromise(function (resolve, reject) {
    // resolve("222");
    reject("bbb");
});
let p2 = promise.then(function (data) {
    console.log("成功1", data);
    // return "222";
    return ppp;
}, function (data) {
    console.log("失败1", data);
    // return "bbb";
    return ppp;
});
p2.then(function (data) {
    console.log("成功2", data);
}, function (data) {
    console.log("失败2", data);
});
// console.log(p2);
// console.log(promise === p2);
</script>

手撕Promise下

  • 1.Promise特点
    • 1.1then方法返回的Promise对象的状态和前一个Promise的状态默认相同
    • 1.2后一个Promise对象的then可以捕获前一个Promise then的异常
    • 1.3catch方法就是then方法的语法糖 then(undefined, function(){});

终极版:

<script>
// 定义常量保存对象的状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise{
    constructor(handle){
        // 0.初始化默认的状态
        this.status = PENDING;
        // 定义变量保存传入的参数
        this.value = undefined;
        this.reason = undefined;
        // 定义变量保存监听的函数
        // this.onResolvedCallback = null;
        // this.onRejectedCallback = null;
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        // 1.判断是否传入了一个函数, 如果没有传入就抛出一个异常
        if(!this._isFunction(handle)){
            throw new Error("请传入一个函数");
        }
        // 2.给传入的函数传递形参(传递两个函数)
        handle(this._resolve.bind(this), this._reject.bind(this));

    }
    then(onResolved, onRejected){
        return new MyPromise((nextResolve, nextReject) => {
            // 1.判断有没有传入成功的回调
            if(this._isFunction(onResolved)){
                // 2.判断当前的状态是否是成功状态
                if(this.status === FULFILLED){
                    try {
                        // 拿到上一个promise成功回调执行的结果
                        let result = onResolved(this.value);
                        // console.log("result", result);
                        // 判断执行的结果是否是一个promise对象
                        if(result instanceof MyPromise){
                            result.then(nextResolve, nextReject);
                        }else{
                            // 将上一个promise成功回调执行的结果传递给下一个promise成功的回调
                            nextResolve(result);
                        }
                    }catch (e) {
                        nextReject(e);
                    }
                }
            }
            // 1.判断有没有传入失败的回调
            // if(this._isFunction(onRejected)){
                try {
                    // 2.判断当前的状态是否是失败状态
                    if(this.status === REJECTED){
                        let result = onRejected(this.reason);
                        if(result instanceof MyPromise){
                            result.then(nextResolve, nextReject);
                        }else if(result !== undefined){
                            nextResolve(result);
                        }else{
                            nextReject();
                        }
                    }
                }catch (e) {
                    nextReject(e);
                }
            // }
            // 2.判断当前的状态是否是默认状态
            if(this.status === PENDING){
                if(this._isFunction(onResolved)){
                    // this.onResolvedCallback = onResolved;
                    this.onResolvedCallbacks.push(() => {
                        try {
                            let result = onResolved(this.value);
                            if(result instanceof MyPromise){
                                result.then(nextResolve, nextReject);
                            }else{
                                nextResolve(result);
                            }
                        }catch (e) {
                            nextReject(e);
                        }
                    });
                }
                // if(this._isFunction(onRejected)){
                    // this.onRejectedCallback = onRejected;
                    this.onRejectedCallbacks.push(() => {
                        try {
                            let result = onRejected(this.reason);
                            if(result instanceof MyPromise){
                                result.then(nextResolve, nextReject);
                            }else if(result !== undefined){
                                nextResolve(result);
                            }else{
                                nextReject();
                            }
                        }catch (e) {
                            nextReject(e);
                        }
                    });
                // }
            }
        });
    }
    catch(onRejected){
        return this.then(undefined, onRejected);
    }
    _resolve(value){
        // 这里是为了防止重复修改
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
            // this.onResolvedCallback(this.value);
            this.onResolvedCallbacks.forEach(fn => fn(this.value));
        }
    }
    _reject(reason){
        if(this.status === PENDING) {
            this.status = REJECTED;
            this.reason = reason;
            // this.onRejectedCallback(this.reason);
            this.onRejectedCallbacks.forEach(fn => fn(this.reason));
        }
    }
    _isFunction(fn){
        return typeof fn === "function";
    }
}
</script>
<script>
// 测试:
let promise = new MyPromise(function (resolve, reject) {
    // resolve();
    // reject();
    setTimeout(function () {
        // resolve();
        reject();
    }, 5000);
});

let p2 = promise.then(function () {
    console.log("成功");
});
p2.catch(function () {
    console.log("失败");
});
// console.log(promise, p2);

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