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

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实例的状态发生改变后,他才会执行。

情况foobar
基本情况一个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);
})

//baz: 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
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
第一篇 JavaScript入门篇 第1章 初步了解JavaScript 1.1 JavaScript是什么 1.2 JavaScript能做什么 1.2.1 表单数据合法性验证 1.2.2 页面特效 1.2.3 交互式菜单 1.2.4 动态页面 1.2.5 数值计算 1.3 JavaScript编程起步 1.3.1 “Hello World!”程序 1.3.2 选择JavaScript脚本编辑器 1.4 如何引入JavaScript脚本代码 1.4.1 通过<script>与</script>标记对引入 1.4.2 通过<script>标记的src属性引入 1.4.3 通过JavaScript伪URL引入 1.4.4 通过HTML文档事件处理程序引入 1.5 嵌入JavaScript脚本代码的位置 1.5.1 在<head>与</head>标记对之间放置 1.5.2 在<body>与</body>标记对之间放置 1.5.3 在两个标记对之间混合放置 1.6 选择合适的浏览器 1.7 处理不支持JavaScript脚本的情况 1.7.1 使用<!——和——>标记对直接屏蔽法 1.7.2 使用<noscript>和</noscript>标记对给出提示信息 1.8 本章小结 1.9 本章习题 第2章 JavaScript编程的语言基础 第3章 JavaScript事件处理 第4章 JavaScript基于对象编程 第5章 文档对象模型(DOM) 第6章 String、Math、Array等数据对象 第7章 Window及相关顶级对象 第8章 Document对象 第9章 HTML元素对象 第二篇 JavaScript进阶篇 第10章 正则表达式 第11章 客户端与服务器端通信 第12章 JavaScript与Ajax技术 第13章 JavaScript错误与异常处理 第三篇 JavaScript实例篇 第14章 JavaScript与插件通信 第15章 JavaScript常用特效收集
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值