小生愛

          


        /**
            *   Promise 特点
            
            *   三种状态 Pending(进行中) Resolved(已完成) Rejected(已失败)
            
            *   一旦状态改变 就不会再变 任何时候都可以得到这个结果 Promise对象的状态改变 有2种
                可能 从Pending -> Resolved 和 Pending -> Rejected 改变后会一直保持这个结果
                对Promise再添加回调 也会立即得到这个结果
        */
        
        
        let isTrue = 1

        // 实例 Promise (resolve, reject)
        let promise = new Promise((resolve, reject) => {
            if (isTrue) {
                // 成功后调用 只能传递一个参数
                resolve(value)
            } else {
                // 失败后调用 只能传递一个参数
                reject(error)
            }
        })

        promise.then(value => {
            // 触发 resolve 调用该方法
        }, (error) => {
            // 触发 reject 调用该方法
        })




        let timeout = ms => {
            // 创建 promise 对象
            return new Promise((resolve, reject) => {
                // 触发resolve方法
                setTimeout(resolve, ms, 'done')
            })
        }

        // resolve 方法触发第一个回调函数
        timeout(1000).then(value => log(value))




        let promise = new Promise((resolve, reject) => {
            log('Promise')
            resolve()
        })

        // then 指定的回调函数 将在当前脚本所有同步任务执行完才会执行
        // 输出 Promise
        // 输出 我在then回调前执行了
        // 输出 Resolved
        // 输出 我也执行了
        promise.then(() => log('Resolved'))

        log('我在then回调前执行了')
        // setTimeout 不是同步任务 所以最后输出
        setTimeout(() => log('我也执行了'), 1000)




        let loadImage = url => {
            // 实例化 promise
            return new Promise((resolve, reject) => {
                let image = new Image()

                // 成功触发 resolve
                image.onload = () => resolve(image)
                // 失败触发 reject
                image.onerror = () => reject('error')
                
                image.src = 'http://wow2004.com/data/qq.jpg'
            })
        }

        // resolve 后的调用第一个then函数
        // reject 后调用第二个then函数
        loadImage()
        .then(value => log(value))
        .then(error => log(error))

        


        let url = 'http://www.wow2004.com/1.php'

        let getData = url => {
            return new Promise( (resolve, reject) => {
                $.ajax({
                    url,
                    dataType: 'jsonp'
                }).done(data => {
                    // 成功调用 resolve
                    resolve(data)
                }).fail(data => {
                    // 失败调用 reject
                    reject('error')
                })
            })
        }

        getData(url)
        .then(data => log(data))
        .then(error => log(error))
        



            /**
                * resolve 接收 promise实例 作为参数 (只有resolve 可以接收promise作为参数)
                  
                p1和p2都是Promise的实例 但是p2的resolve方法将p1作为参数 即一个异步操作的结果
                是返回另一个异步操作

                这时p1的状态就会传递给p2 p1的状态决定了p2的状态 如果p1的状态是Pending 那么p2
                的回调函数就会等待p1的状态改变 如果p1的状态已经是Resolved或者Rejected 那么p2
                的回调函数将会立刻执行
            */
            let p1 = new Promise((resolve, reject) => {
                setTimeout(() => resolve('错误'), 3000)
            })

            let p2 = new Promise((resolve, reject) => {
                setTimeout(() => resolve(p1), 1000)
            })

            p2.then(
                result => log(result),
                error => log(error)
            )




            // then方法返回的是一个新的Promise实例 (不是原来那个Promise实例) 
            // 因此可以采用链式写法 即then方法后面再调用另一个then方法
            // 第一个回调函数完成以后 会将返回结果作为参数 传入第二个回调函数
            // 采用链式的then 可以指定一组按照次序调用的回调函数
            let promise = new Promise((resolve, reject) => resolve(1))

            let p = promise.then(
              x => x + 1,
              y => log(y)
            ).then(
              x2 => log(x2),
              y2 => log(y2)
            )




            let promise = new Promise((resolve, reject) => {
              resolve('ok')
            })

            // 建议不要在then方法里定义 reject 状态的回调 总是使用catch
            // 因为 catch 可以捕获then方法中的错误 也更接近同步的写法
            promise
            .then(x => log(x))
            .catch(err => log(err))




            // Promise 对象的错误具有冒泡性质 会一直向后传递 直到被捕获为止
            let some = function () {
              return new Promise((resolve, reject) => {
                resolve(2)
              })
            }

            some()
            .then(x => log(x))
            .then(() => { throw new Error('test') })
            .catch(err => log(err))




            // 分开写的promise 最多适用2层 ajax 嵌套 第三层没法写
            let p1 = new Promise(resolve => {
                setTimeout(() => {
                    resolve('p1')
                }, 3000)
            })

            p1.then(value => {
                log(value)
            })

            let p2 = new Promise(resolve => {
              resolve(p1)
            })

            p2.then(
              x => log('p2')
            )




            let p1 = new Promise(resolve => {
                resolve('p1')
            })

            // 第一个then 会把返回结果作为参数 传入第二个回调函数
            p1.then(v1 => {
                return v1
            }).then(v2 => {
                // v2 == v1
                log(v2)
            })




            let p1 = new Promise(resolve => {
                setTimeout(() => resolve('第一个promise执行完成'), 3000)
            })

            // 前一个回调函数 有可能返回的还是一个Promise对象 
            // 这时后一个回调函数会等待该Promise对象的状态发生变化才会被调用
            p1.then(v1 => {
                log(v1)
                // 这里必须添加一个return 以返回一个promise 
                return new Promise(resolve => {
                    setTimeout(() => resolve('等待执行完, 才会执行下一个then'), 3000)
                    
                })
            }).then(v2 => {
                log(v2)
                return new Promise(resolve => {
                    setTimeout(() => resolve('最后一个promise'), 3000)
                })
            }).then(v3 => {
                log(v3)
            })




            let p1 = new Promise(resolve => {
                resolve('第一个promise执行完成')
            })

            // catch 会捕获所有then产生的错误
            p1.then(v1 => {
                return new Promise(resolve => {
                    resolve('等待执行完, 才会执行下一个then')
                })
            }).then(v2 => {
                // 这里抛出错误
                x + 1
            }).catch(err => log(err))
            




            /*
                *   Promise.all 用于将多个Promise实例 包装成一个新的Promise实例
                   
                *   包含两种状态
                    1) 只有p1 p2 p3的状态都变成已完成 Promise.all的状态才会变成已完成
                       此时p1 p2 p3的返回值组成一个数组 传递给p的回调函数
                    
                    2) 只要p1 p2 p3之中有一个被rejected Promise.all的状态就变成 rejected
                       此时第一个被reject的实例的返回值 会传递给Promise.all 的回调函数
            */
            let p1 = new Promise(resolve => {
                setTimeout(() => resolve(1), 1000)
            })

            let p2 = new Promise(resolve => {
                setTimeout(() => resolve(2), 2000)
            })

            let p3 = new Promise(resolve => {
                setTimeout(() => resolve(3), 1000)
            })

            Promise.all([p1, p2, p3])
            .then(v => log(v))
            .catch(err => log(err))




            // 如果没给then 返回值就是resolve返回的参数
            // 如果给了then 返回值是then里return的值
            let p1 = new Promise(resolve => {
                setTimeout(() => resolve(1), 1000)
            }).then(x => {
                // 如果不给return Promise.all接收的返回值是空
                return x
            })

            let p2 = new Promise(resolve => {
                setTimeout(() => resolve(2), 3000)
            })

            Promise.all([p1, p2])
            .then(v => log(v))
            .catch(err => log(err))




            // Promise.all 后面继续添加then
            let p1 = new Promise(resolve => {
                setTimeout(() => resolve(1), 1000)
            })

            let p2 = new Promise(resolve => {
                setTimeout(() => resolve(2), 3000)
            })

            Promise.all([p1, p2])
            .then(v => {
                // 必须添加return 后面的then才会等待这个promise执行完 再执行
                return new Promise(resolve => {
                    setTimeout(() => {
                        log('等待执行完')
                        resolve('我执行完了')
                    }, 3000)
                })
            })
            .then(v => log('我开始执行'))
            .catch(err => log(err))