Promise

作者: 阿布朗迪 | 来源:发表于2018-11-22 20:21 被阅读0次

ES规定,Promise对象是一个构造函数,用来生成Promise实例

const promise = new Promise(function(resove,reject){
 // some code
 if(/* 异步操作成功 */){
        resolve(value);
} else {
        reject(error);
}
});

Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject。它们是两个函数,由JavaScript引擎提供,不用自己部署。

resolve函数的作用是,将Promise对象的状态从"未完成"变成"成功"(即从pending变为resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用是,将Promise对象的状态从"未完成"变为"失败"(即从pending变为rejected),在异步操作失败时调用,并将异步 操作报出的错误,作为参数传递出去。

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

promise.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 )
})

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

** Promise 新建后就会立即执行。**

let promise = new Promise((resolve,reject)=>{
   console.log("Promise");
   resolve();
});

promise.then(function(){
   console.log( "resolved.");
})

console.log( "hi")

//Promise
//hi
//resolved

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

下面是异步加载图片的例子。

function loadImageAsync(url){
    return new Promise((resolve,reject) =>{
        const image = new Image();

        image.onload = ()=>{
            resolve(image);
        };

        image.onerror = ()=>{
            reject( new Error("Could not load image at" + url));
        };

        image.src = url;
    })
}

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

下面是一个用Promise对象实现的Ajax操作的例子。

const getJSON = function(url){
    const promise = new Promise(function(resolve,reject){
        const handler = function(){
            if(this.readyState !== 4){
                return ;
            }
            if(this.status === 200){
                resolve(this.response);
            }else{
                reject(new Error(this.statusText));
            }
        };
        const client = new XMLHttpRequest();
        client.open("GET",url);
        client.onreadystatechange = handler;
        client.responseType = "json";
        client.setRequestHeader("Acceot","application/json");
        client.send();
    });

    return promise;
}
getJSON("/post.json").then(function(json){
    console.log( "Contents: "+json);
},function(error){
    console.error("出错了",error)
});

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

如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例,表示抛出错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例,比如像下面这样。

const p1 = new Promise(function(resolve,reject){
    //...
})

const p2 = new Promise(function(resolve,reject){
    //...

    resolve(p1)
})

上面代码中,p1p2都是Promise的实例,但是p2resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。

注意,这是p1的状态就会传递给p2也就是说,p1的状态决定了p2的状态。如果p1的状态是pending,那么p2的函数就会等待p1的状态 改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数 将会立即执行。

const p1 = new Promise(function(resolve,reject){
    setTimeout(()=> reject(new Error("fail")),3000)
})

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

p2.then(result => console.log(result))
  .catch(error => console.log(error))

上面的代码中,p1是一个 Promise ,3秒之后变为rejectedp2的状态在 1 秒之后改变,resolve方法返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1变为rejected,导致触发catch方法指定的回调函数。

注意,调用resolvereject并不会终结Promise 的参数函数的执行。

new Promise(function(resolve,reject){
    resolve(1);
    console.log( 2);
}).then(r => {
    console.log(r )
})

//2
//1

上面的代码中,调用resolve(1)以后,后面的console.log(2)还是会执行的,并且会首先打印出来,这是因为立即 resolved 的 Promise 是在本轮事件循环的末尾执行,后续操作应该放到then方法里面,而不应该直接写在resolvereject的后面。所以,最好在它们的前面加上return语句。这样就不会有意外了。

new Promise(function(resolve,reject){
    return resolve(1);
    //后面的语句不会执行
    console.log( 2 )
})

相关文章

网友评论

      本文标题:Promise

      本文链接:https://www.haomeiwen.com/subject/ixmlqqtx.html