• Promise


    Promise对象用于一个异步操作的成功(或失败)及其结果值的表示。(简单点说,就是我们处理异步请求,经常会进行一些承诺,如果我赢了你嫁给我,我输了我嫁给你,这类的诺言,这就是Promise的中文意思,一个诺言,一个成功,一个失败)

    ES6将其写进了语言标准,统一了用法,并且原生提供了Promise对象。

    我们可以先看一下Promise到底是什么?chrome上输入console.dir(Promise),就出来了。

    我们可以看到,原来Promise是个构造函数,它有all,race,reject,resolve方法,在其原型prototype上有catch,then方法。

    有的初级的小伙伴就问了,呀呀呀,这个Promise怎么还有方法呢?Promise也是函数哦,函数是对象,当然可以有方法啦,0--^^--0。毫无疑问,原型prototype上的方法就是供Promise的实例对象使用的。

    Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript引擎提供,不用自己部署。resolve函数的作用是,将Promise对象的状态从“”未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果作为参数传递出去;reject函数的作用是,将Promise对象的状态从“”未完成”变为“失败”,在异步操作失败时调用,并将异步操作的错误作为参数传递出去;

    既然这样,我们先实例化一个Promise。

    var promise = new Promise(function(resolve, reject) {
        setTimeout(resolve('some thing happed'), 200)
    })
    promise.then(function(data){
         console.log('success:', data) 
    }, function(err){
         console.log('error:', err)
    })

    首先得说明,Promise.prototype.then,可以接受两个回调函数,当成功resolve时调用第一个回调,失败时调用第二个回调,第二个回调可以省略。

    所以上面的结果为 success: some thing happed 

    初步了解Promise后,我们用Promise对象实现一个AJAX操作的例子。

    var getJSON = function(url) {
        var promise = new Promise(resolve, reject) {
            var client = new XMLHttpRequest();
            client.open('GET', url);
            client.onreadystatechange = function(){
                if (this.readyState !== 4) {
                    return
                }
                if (this.status === 200) {
                    resolve(this.response)
                } else {
                    reject(new Error(this.statusText))
                }
            }    
        }
        return promise
    }
    
    getJSON('/db.json').then(function(json){
        console.log('Result:',  json)    
    }, function(error){
        console.log('error:', error)
    })

    上面的代码中,getJSON是对XMLHttpRequest对象的Promise封装,用于发出一个针对JSON数据的HTTP请求,并返回一个Promise对象。需要注意的是,在getJSON内部,resolve函数和reject函数调用时都带有参数。reject函数的参数通常是Error对象的实例,而resolve函数的参数除了正常的值外,还可以是另一个Promise对象。

    举例说明

    var p1 = new Promise(function (resolve, reject) {
        setTimeout(() => reject(new Error('fail')), 3000)
    })
    var p2 = new Promise(function (resolve, reject) {
        setTimeout(() => resolve(p1), 1000)
    })
    p2.then(result => console.log('success:', result))
    p2.catch(error => console.log('error:', error))

    在这种情况下,p1的状态会传递给p2,p1的状态决定了p2的状态,一秒钟后,p1的状态还是pending,所以p2也是pending,三秒后,p1的状态变为failed,p2的状态也变为failed,所以调用catch方法,返回结果为error: Error: fail,利用这个特性,我们可以用来控制多个异步操作的流程???

    需要注意的是Promise.prototype.then方法和Promise.prototype.catch方法返回的都是Promise对象,所以可以继续调用then方法。

    前面有看到,Promise构造函数有all和race方法,让我们逐一击破

    Promise.all方法用于将多个Promise实例包装成一个新的Promise实例

    var p = Promise.all([p1, p2, p3])

    此时p的状态有p1,p2,p3的状态决定,规则有两条,

    1、只有p1,p2,p3的状态都变成Fullfilled时,p的状态才会变成Fullfilled,此时p1,p2,p3的返回值组成一个数组,传递给p的回调函数

    2、只要p1,p2,p3中一个被Rejected,p的状态就变成Rejected,此时第一个被Rejected的实例的返回值传递给p的回调函数

    这就是all的意义啦。比如

    var promises = [2,3,4].map(function(id){
        return getJSON('/post/' + id + '.json'); 
    })
    Promsie.all(promises).then(function(posts){
        //3个各自成功返回值组成的数组
    }).catch(function(reason){
        //第一个失败返回值
    })

    Promise.race()同样是将多个Promise实例包装成一个新的Promise实例

    var p = Promise.race([p1,p2,p3])

    只要p1,p2,p3中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的回调函数。就不在赘述。

    前面也有看到,Promise构造函数还有resolve和reject方法,它们各自又有什么用呢?

    有时,我们需要将现有对象转化为Promise对象,Promise.resolve方法就起到这个作用。如 

    var jsPromise = Promise.resolve($.ajax('/whatever.json'));
    jsPromise.then(function(data){
        //成功
        console.log('success:', data)
    },function(err){
        //失败
        console.log('error:', err)
    })

    上面的代码可以将jquery生成的deferred对象转化新的Promise对象,jsPromise调用哪个方法还是取决于jquery中deferred对象的状态。

    Promise.resolve('foo') 等价于 new Promise(resolve => resolve('foo'))

    如果Promise.resolve方法的参数不是具有then()方法的对象,则返回一个新的Promise对象,且其状态为Resolved。

    var p = Promise.resolve('Hello')
    p.then(function(s){
        console.log(s)
    })
    //hello

    由于字符串'hello'不属于异步操作(没有then方法),返回Promise实例的状态从一生成就是Resolved,所以回调函数会立即执行。

    Promise.reject(reason)则是返回一个新的Promise实例,状态为Rejected。Promise.reject方法的参数reason会被传递给实例的回调函数

    var p = Promise.reject('出错了')
    //等同于
    var p = new Promise((resolve,reject) => reject('foo'))
    p.then(null, function (s) {
       console.log(s)
    })
    //出错了
  • 相关阅读:
    第01组 Beta冲刺(4/5)
    第01组 Beta冲刺(3/5)
    第01组 Beta冲刺(2/5)
    第01组 Beta冲刺(1/5)
    2019 SDN上机第6次作业
    2019 SDN阅读作业(2)
    2019 SDN上机第5次作业
    第01组 Alpha事后诸葛亮
    第01组 Alpha冲刺(6/6)
    团队作业第三次—项目需求分析
  • 原文地址:https://www.cnblogs.com/wbxjiayou/p/7203479.html
Copyright © 2020-2023  润新知