从零开始学_JavaScript_系列(48)——Promise(1)基础知识

来源:互联网 发布:软件开发人员薪酬 编辑:程序博客网 时间:2024/06/05 07:59

1、是什么

  1. 一个十分适合处理异步操作的对象
  2. 有进行中(pending)、成功(resolved)、失败(rejected)三种状态
  3. 可以轻松处理成功或失败的情况,代码结构更清爽,操作结果可预期
  4. 对象的状态不受外界影响,只会根据预先设定的情况执行代码,方便从pending状态切换到resolved或者rejected
  5. Promise对象在创建后会立即执行,但他的then是异步的(即使状态立刻改变,也要等其他代码执行完毕后才会去执行)
  6. Promise对象的状态改变是一次性的,改变后值即确定。不会因为任何情况导致状态反复变化
  7. Promise的状态改变后,会立刻触发其回调函数(执行resolve或者reject)
  8. Promise对象foo可以作为另外一个Promise对象bar的值,并且在foo和bar的状态都不是pending后,才会执行bar的回调
  9. Promise对象的then的值是Promise对象,但和最初的Promise不是同一个
  10. then可以连写,方便连续异步函数的调用
  11. Promise.all可以轻松处理多个异步操作,在全部完成后才应执行的逻辑
  12. Promise.race可以轻松处理多个异步操作,但只需要最快的那个异步操作结果的情况
  13. Promise.resolve和Promise.reject可以轻松将一个变量转为Promise对象并使用

2、基本例子

Promise有几个特点:

  1. new出来后立刻执行;
  2. 只执行一次,并且结果发生后,无论之后几次调用then,都只执行那唯一一个结果(resolve或者reject);
  3. 如果处于pending中,那么执行then时,相当于添加到队列里,pending中不执行,但等结果出来后,会一起执行(而非只执行一个或者不执行);
  4. resolve或者reject只能接受一个参数,如果要传多个参数的话,请使用数组或者对象的形式;
  5. resolve和reject里函数不是在声明时执行,而是异步的,在判定promise的状态为非pending状态时执行;

如以下示例:

console.log(new Date);let foo = new Promise(function (resolve, reject) {    setTimeout(function () {        //获取毫秒的数值        var d = (new Date()).getMilliseconds();        if (d % 2 === 0) {            resolve([new Date(), d]);        } else {            reject([new Date(), d]);        }    }, 1000);})foo.then(function (arr) {    console.log(new Date);    console.log("resolve: " + arr[0]);}, function (arr) {    console.log("reject: " + arr[0]);})foo.then(function (arr) {    console.log(arr[1]);    console.log("resolve: " + arr[0]);}, function (arr) {    console.log(arr[1]);    console.log("reject: " + arr[0]);})//Tue Jul 04 2017 00:06:52 GMT+0800 (中国标准时间)/* 然后,1秒后 *///reject: Tue Jul 04 2017 00:06:53 GMT+0800 (中国标准时间)//633//reject: Tue Jul 04 2017 00:06:53 GMT+0800 (中国标准时间)

以上代码证明了第2,3,4点。而第一点和第五点通过以下代码证明:

let foo = new Promise(function (resolve, reject) {    resolve();    console.log("in Promise");})console.log("after Promise");foo.then(function (arr) {    console.log("in resolve");});console.log("at last");//in Promise//after Promise//at last//in resolve

证明除了resolve和reject中的代码是异步的之外,其他都是顺序执行(位于foo.then后的代码先执行,之后才执行了foo.then的回调函数)。

3、当两个Promise对象发生交互时

具体来说,Promise实例在执行回调函数时可以传一个参数,而这个参数可以是另外一个Promise实例的回调函数。如代码:

let foo = new Promise(function (res, rej) {    setTimeout(function () {        res("1")    }, 1000)})let bar = new Promise(function (res, rej) {    res(foo);    //参数是foo实例})

在这种情况下,bar的回调函数并不会立即执行,而是会等待foo的状态改变后,再去执行bar的回调函数。

即当Promise实例bar的回调函数的参数是另外一个Promise实例foo时,bar在状态改变后不会立即执行,而是等待前一个Promise实例的状态发生改变后,他才会执行。

情况 foo bar 基本情况 一个Promise实例 bar的then的回调函数的参数是foo 延迟等待时间:foo小于bar 先执行 后执行 延迟等待时间:foo大于bar 先执行 等待foo执行完后即执行

如代码:

let foo = new Promise(function (res, rej) {    setTimeout(function () {        res("1")    }, 1500)})let bar = new Promise(function (res, rej) {    setTimeout(function () {        console.log(bar);    }, 1000)    setTimeout(function () {        res(foo);    }, 500)})let baz = new Promise(function (res, rej) {    res("3");})foo.then(function (val) {    console.log("foo: " + val);})bar.then(function (val) {    console.log("bar: " + val);})baz.then(function (val) {    console.log("baz: " + val);})//bar: 3//状态为"pending"//foo: 1//bar: 1

如上代码:

  1. bar因为没有延迟,也没有依赖,所以先执行了;
  2. bar虽然500ms后就可以执行,但因为依赖于bar,所以在等待foo执行,注意,此时其状态依然为pending,而不是resolved;
  3. foo在1500ms后执行完毕;
  4. bar发现foo执行完毕了,自己也可以执行,所以跟着执行了;

除此之外,还有几个特点:

  1. 作为参数的Promise实例,他会将自己的参数的值传递给另一个Promise实例,即bar的resolve的参数是foo,而foo的resolve的参数的值是”1”,因此bar的resolve的参数的值是”1”;
  2. 两个Promise实例要执行的必须都是resolve或者都是reject,不然不会互相影响;
阅读全文
0 0