14.1、Promise


        /*
            Promise 含义:

            Promise 是异步编程的一种解决方案,比传统解决方案 ———— 回调函数和事件 ———— 更合理且更强大。
            它最早由社区提出并实现,es6 将其写进了语言标准,统一了用法,并原生提供了 Promise 对象。

            所谓 Promise,简单来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
            从语法上来说,Promise 是一个对象,从可以获取异步操作的消息。
            Promise 提供统一的 Api ,各种异步操作都可以用同样的方法处理。
        */


        /*
            Promise 对象有以下两个特点:

                1. 对象的状态不受外界影响。Promise 对象代表一个异步操作,有 3 种状态:Pending(进行中)、Fulfilled(已成功)、和 Rejected(已失败)
                只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

                2. 一旦状态改变就不会再变,任何时候都可以得到这个结果。
                Promise 对象的状态改变只有两种可能:从 Pending 变为 Fulfilled 和 从 Pending 变为 Rejected。
                只要这两种情况发生,状态就凝固了,不会再变,而是一直保持这个结果,这时就称为 Resolved(已定型)。
                就算改变已经发生,再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同。事件的特点是:如果错过了它,再去监听是得不到结果的。


            (注意:一般 Resolved 统一指 Fulfilled 状态,不包含 Rejected状态)
        */


        /*
            有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数,此外,Promise 提供统一的接口,使得控制异步操作更加容易。

            Promise 也有一些缺点:
                首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
                其次,如果不设置回调函数,Promise 内部抛出得错误不会反应到外部。
                再者,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

                如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署 Promise 更好的选择。
        */


        /*
            Promise 基本用法:

            es6 规定,Promise 对象是一个构造函数,用来生成 Promise 实例
        */ 
        
        // 下面的代码创造了一个 Promise 实例
        var promise1 = new Promise(function(resolve, reject) {
            // ...some code 

            if ( true ) {         // 异步操作成功
                resolve(value)
            } else {              // 异步操作失败
                reject(error)
            }
        })

        /*
            Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject ,它们是两个函数,由 javascript 引擎提供,不要自己部署

            resolve 函数的作用是,将 Promise 对象的状态从 “未完成” 变为 “成功” (即从 Pending 变为 Resolved),在异步操作成功时调用,并将异步操作的结果作为参数传递出去;
            reject 函数的作用是:将 Promise 对象的状态从 “未完成” 变为 “”失败 (即从 Pending 变为 Rejected),在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去
        */

        // Promise 实例生成之后,可以用 then 方法分别指定 Resolved 状态 和 Rejected 状态的回调函数
        promise1.then(function(value) {
            // success
        }, function(error) {
            // failure
        })

        /*
            then 方法可以接受两个回调函数作为参数。
            第一个回调函数是 Promise 对象的状态变为 Resolved 时调用,第二个回调函数是 Promise 对象的状态变为 Rejected 时调用。
            其中,第二个参数是可选的。
            这两个函数都接受 Promise 对象传出的值作为参数
        */

        // 下面是一个 Promise 对象的简单例子:
        function timeout(ms) {
            return new Promise((resolve, reject) => {
                setTimeout(resolve, ms, 'done')
            })
        }

        timeout(100).then((value) => {
            console.log(value)      // 100ms 后打印 done
        })

        // 上面的代码中,timeout 方法返回一个 Promise 实例,表示一段时间以后才会发生的结果,过了指定的时间(ms参数)以后,Promise实例的状态变为 Resolved,就会触发 then 方法绑定的回调函数

        // Promise 函数新建后就会立即执行

        let promise2 = new Promise(function(resolve, reject) {
            console.log('Promise')
            resolve()
        })

        promise2.then(function() {
            console.log('Resolved')
        })

        console.log('Hi!')

        // Promise
        // Hi!
        // Resolved

        // 上面的代码中,Promise 新建后会立即执行,所以首先输出的是 Promise 。
        // ****然后,then 方法指定的回调函数将在当前脚本所有同步任务完成后才会执行,所以 Resolved 最后输出。****



        // 下面是异步加载图片的例子:
        function loadImgAsync(url) {
            return new Promise(function(resolve, reject) {
                var image = new Image()

                image.onload = function() {
                    resolve(image)
                }

                image.onerror = function() {
                    reject(new Error('Could not load image at ' + url))
                }

                image.src = url
            })
        }

        // 上面的代码中使用 Promise 包装了一个图片加载的异步操作。如果加载成功,就调用 resolve 方法,否则调用 reject 方法


        // 下面是一个用 Promise 对象实现的 AJAX 操作的例子:
        var getJSON = function(url) {
            var promise3 = new Promise(function(resolve, reject) {
                var client = new XHLHttpRequest()
                client.open('GET', url)
                client.onreadystatechange = handler
                client.responseType = 'json'
                client.setRequestHeader('Accept', 'application/json')
                client.send()

                function handler() {
                    if (this.readyState !== 4) {
                        return 
                    }
                    if (this.readyState === 200) {
                        resolve(this.response)
                    } else {
                        reject(new Error(this.statusText))
                    }
                }
            })
            return promise3
        }

        getJSON('/posts.json').then(function(json) {
            console.log('Contents: ' + json)
        }, function(error) {
            console.log('出错了' , error)
        })

        // 上面的代码中,getJSON 是对 XMLHttpRequest 对象的封装,用于发出一个针对 JSON 数据的 HTTP 请求,并返回一个 Promise 对象。
        // 需要注意的是,在 getJSON 内部,resolve 函数和 reject 函数调用时都带有参数

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值