前端开发技术语言_Promise系列

濮阳前端开发招聘|前端开发校园招聘|前端开发手机端适配问题

参考的书籍是:
1.http://es6.ruanyifeng.com/#docs/promise;
2.http://liubin.org/promises-book/;
3.《你不知道的JavaScript中卷》、《英文版》

本文是第二篇。
第一篇文章对相关术语说的不详细,本文详细说说。
先看一下下面的代码:
[quote]var p = new Promise(function(resolve, reject) {
resolve(20);
});
p.then(
function onFulfilled() {},
function onRejected() {}
);[/quote]

1.基本术语

其中promise表示承诺,即对某一件事情的承诺:这个事情,交给我了,你放心吧。
然而此承诺是有状态的,进行中、已完成、已拒绝。
其中已完成是指,事情办成了,而拒绝是指,事情办砸了。
不论是办成还是办砸,那么此事情都是办完了。
办完了,就是说此承诺已决议了。
而得到承诺的人,会对承诺的决议结果(完成或拒绝)会所响应,未决议是不会相应的。

这里的几个名词有对应的英文,
状态:进行中(pending)、已完成(fulfilled)、已拒绝(rejected)
已决议(resolved):已完成、已拒绝
未决议:进行中
响应:完成回调(onFulfilled)、拒绝回调(onRejected)

注:状态可以通过console.log查看其[[PromiseStatus]]属性值。
参考文献一上面认为,已完成也用resolved单词表示,浏览器打印的结果确实是这样的。
本文更偏向于参考文献3的观点,认为resolve是决议,状态结果是包含完成的,个人觉得这样会更好理解一些。请看下面的论述。

2.resolve是决议不只是完成

看上面的代码,我们发现,构造函数的参数(函数)的参数传递的名字是resolve和reject,并不是fulfill和reject。
虽然参数名字可以随便起,但是用resolve而不是fulfill是有用意的。
这里我们把resolve和reject当作动词来用
调用了reject表示,状态进入已拒绝。
调用resolve表示,状态结果需要进一步决议,最终结果可能是未决议,也可能是已决议(已完成、已拒绝)。

这里有必要再强调的一点是单词resolve,是决议而不是完成的意思。看如下的代码:
html 代码

<script>
    var p = new Promise(function (resolve, reject) {
        resolve(Promise.reject(‘no!’));
    });
    p.then(
        function onFulfilled() { },
        function onRejected(msg) {
            alert(msg);
        }
    );
</script>

上面的代码中,构造函数内部虽然调用的是resolve,但是then方法注册的拒绝回调触发了。

所以Promise.resolve其api的含义不是类似于Promise.reject那样,
直接生成一个状态为完成的promise实例。

而是说看参数情况,我们决议一下吧:
html 代码

<script>
    var p = Promise.resolve(30);
    p.then(
        function (value) {
            alert(value);
        },
        function () { }
    );
</script>

上面走的是完成回调,说明p的状态决议成了完成。

如果参数已经是promise实例的话,直接返回该实例:
html 代码

<script>
    var p = Promise.resolve(new Promise(function (resolve, reject) {
        reject(‘no!’)
    }));
    p.then(
        function () {
        },
        function (msg) {
            alert(msg);
        }
    );
</script>

当然上述实例p的决议状态是拒绝。

如果传进是thenable,会封装成promise实例:
html 代码

<script>
    var o = {
        then: function (resolve, reject) {
            reject(‘no’);
        }
    };
    var p = Promise.resolve(o);
    p.then(
        function () {
        },
        function (msg) {
            alert(msg);
        }
    );
</script>

来个一直等待中的情形。
html 代码

<script>
    var p = Promise.resolve(new Promise(function (resolve, reject) {
        alert(‘unresolved’);
    }));
    p.then(
        function () {
            alert(‘fulfilled’)
        },
        function () {
            alert(‘rejected’);
        }
    );
</script>

其实,我们可以这么想一下,某人求我办件事情,我转而拜托另一个人,进而把他给我的承诺抛给了之前的那个某人。
resolve表示决议的结果取决于另一个人,他可能完成,可能拒绝,甚至也可能一直处于进行中。

3.完成值和拒绝值
不管决议的结果是完成还是拒绝,都会相应的拿到最终的值。
比如上面的30是完成值,no!是拒绝值。
完成值,总是需要编程给出的,而拒绝值一般也称为拒绝原因。
拒绝值,不一定需要编程给出:
html 代码

<script>
    var p = new Promise(function (resolve, reject) {
        throw new Error(‘no!’);
    });
    p.then(
        function () {
        },
        function (msg) {
            alert(msg);
        }
    );
</script>

上面是直接抛出异常,假如是语法错误呢:
html 代码

<script>
    var p = new Promise(function (resolve, reject) {
        xxx
    });
    p.then(
        function () {
        },
        function (msg) {
            alert(msg);
        }
    );
</script>

看到resolve调用时,可以传进promise实例,那么reject也传一下试试:
html 代码

<script>
    var p = new Promise(function (resolve, reject) {
        reject(Promise.resolve(2));
    });
    p.then(
        function () {
        },
        function (msg) {
            alert(msg);
        }
    );
</script>

证明了,reject传进的东西,只会当成拒绝值,而不像resolve有递归的味道在里面。

注:此值可以通过console.log查看其属性[[PromiseValue]]。

4.只能决议一次
决议的结果,要么不决议(未决议,pending),要么完成,要么拒绝,只能3选一。
html 代码

<script>
    var p = new Promise(function (resolve, reject) {
        resolve(2);
        reject(‘no!’);
    });
    p.then(
        function (value) {
            alert(value);
        },
        function (msg) {
            alert(msg);
        }
    );
</script>

上面的代码中,可以看出如果一开始决议是完成的话,那么后面的拒绝就没有用了。

关于决议只能有一次机会,通过点击按钮决议能更好的说明:
html 代码

<button id=”success”>success</button>
<button id=”failure”>failure</button>
<script>
    var s = document.querySelector(‘#success’);
    var f = document.querySelector(‘#failure’);
    var resultOfPromise = new Promise(function (resolve, reject) {
        s.onclick = function () {
            resolve();
        };
        f.onclick = function () {
            reject();
        };
    });
    resultOfPromise.then(
        function () {
            alert(‘success’);
        },
        function () {
            alert(‘failure’)
        }
    );
</script>

如果你知道构造函数的参数(是个函数)是同步执行的话,
可能会想我在外边并且异步决议的话,是否也是这样的,答案仍然是的。
html 代码

<script>
    var outer = {};
    var p = new Promise(function (resolve, reject) {
        outer.resolve = resolve;
        outer.reject = reject;
    });
    p.then(
        function (value) {
            alert(value);
        },
        function (msg) {
            alert(msg);
        }
    );
    setTimeout(function () {
        outer.resolve(2);
        outer.reject(‘no’);
        outer.resolve(3);
    }, 1000);
</script>

其实这种写法有点像Deferred了。
这个第4点,个人觉得是promise的最重要一点。

前端开发技能点|前端开发vscode插件|web 前端开发技术ppt

赞(0)
前端开发者 » 前端开发技术语言_Promise系列
64K

评论 抢沙发

评论前必须登录!