【ECMAScript6】 Promise

2019-03-14  本文已影响0人  zbcy0012

Promise 是什么

Promise 是 ES6 为 JavaScript 异步编程定义的全新 api 。为异步编程而生,实际上就是另类的回调函数。

为什么要使用 Promise

API速查

使用方法

promise() 之后总是会返回一个新的 promise 对象,因此而支持链式操作。

1.基本用法

const _p = new Promise((resolve, reject) => {
    console.log(1);
    resolve(2);
});

_p.then(
    res => {
        console.log(res);
    },
    err => {
        console.log(err);
    }
);
*************
1
2

resolve 为当异步处理“成功”时调用的方法;reject 为异步处理“失败”时调用的方法。

2.链式操作

const _p = new Promise((resolve, reject) => {
    console.log(1);
    resolve(2);
});

_p.then(
    res => {
        console.log(res);
        return 3;          //把想要继续操作的数据 return 出来
    },
    err => {
        console.log(err);
    }
).then(res => {
    console.log(res);
});
*******************
1
2
3

行为探究

1.时效性

const _p = new Promise((resolve, reject) => {
    console.log(1);  //  这一条语句模拟了声明内容
    resolve(2);
});

_p.then(res => {
    console.log(res);
    return 3;
}).then(res => {
    console.log(res);
});
*************
1    
2   
3   
const _p = new Promise((resolve, reject) => {
    //这里属于声明内容
    setTimeout(() => {
        console.log(1);
        resolve(2);
    }, 1000);
});

_p.then(res => {
    console.log(res);
    return 3;
}).then(res => {
    console.log(res);
});
******************
1    //1秒后打印
2    //1秒后打印
3    //1秒后打印
const getp = () => {
    //这里的 promise 对象是函数返回结果,所以直到函数 getp 被调用之前,
    //该promise 的声明内容都不在主线程当中,所以不会被立即执行。
    return new Promise((resolve, reject) => {
        console.log(1);
        resolve(2);
    });
};

setTimeout(() => {
    const _p = getp();
    _p.then(res => {
        console.log(res);
        return 3;
    }).then(res => {
        console.log(res);
    });
}, 2000);
**************
1    //2秒后打印
2    //2秒后打印
3    //2秒后打印
let _p = new Promise((resolve, reject) => {
    console.log(1);
    resolve(2);
});

//完成处理程序
_p = _p.then(res => {
    console.log(res);
    return 3;
});

//完成处理程序
_p.then(res => {
    console.log(res);
    return 4;
});

console.log(11);
*****************
1    
11
2    //完成处理程序被添加至任务队列末尾
3    //完成处理程序被添加至任务队列末尾

【结论】
1. promise 的声明环境如果在主线程当中,那么其声明内容会被立即调用一次;而在 resolvereject 中传入的参数知道有下一次 .then() 动作时才会被使用。
2. promise 的完成处理程序(resolve)和拒绝处理程序(reject)总是在执行器完成后被添加到任务队列的末尾。

2.报错机制

const _p = new Promise((resolve, reject) => {
    throw new Error(233);
});

_p.then(
    res => {
        console.log(res);
        return 3;
    }
    //此处不注册拒绝处理程序
);
***************
弹出错误
const _p = new Promise((resolve, reject) => {
    throw new Error(233);
});

_p.then(
    res => {
        console.log(res);
        return 3;
    },
    //注册拒绝处理程序
    err => {
        console.log(err);
    }
);
***************
不弹出错误,打印错误信息
const _p = new Promise((resolve, reject) => {
    throw new Error(233);
});

_p.then(
    res => {
        console.log(res);
        return 3;
    },
    //注册拒绝处理程序(但没有任何动作)
    err => {
        //console.log(err);
    }
);
***************
完全不报错
const _p = new Promise((resolve, reject) => {
    console.log(2);
    resolve(2);
    console.log(3);
    throw new Error(233);
    console.log(4);
});

_p.then(
    res => {
        console.log(res);
        return 3;
    },
    //无论是否注册拒绝处理程序
    err => {
        console.log(err);
    }
);
*********
2
3
2
完全不报错
const _p = new Promise((resolve, reject) => {
    console.log(2);
    throw new Error(233);
    console.log(3);
    resolve(2);
    console.log(4);
});

_p.then(
    res => {
        console.log(res);
        return 3;
    },
    err => {
        console.log(err);
    }
);
**********
2
打印错误信息

【结论】
1. 在 promise 进程中如果先遇到了 resolve 则后续即便遇上 error 也不会调用 reject;反之如果先遇到 error 则直接调用 reject,且永远不调用完成处理程序。

上面的例子我们发现 resolve 之后的语句依然会被执行,直到遇见 error 或结束;反之 Error 之后的语句则无论如何都不会被执行了。

2. 永远不要声明一个什么都不做的拒绝处理函数,因为你可能会在出现bug时得不到任何有效信息。

------------- 作者水平有限,如有错误,欢迎探讨指正 -------------

上一篇下一篇

猜你喜欢

热点阅读