Promise

Posted songya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise相关的知识,希望对你有一定的参考价值。

为什么要有Promise?

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

一、Promise的特点

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

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

二、基本用法

const promise = new Promise(function(resolve, reject){
    // ... some code

    if(/*异步操作成功*/){
        resolve(value);
    }else{
        reject(error);
    }
})

Promise的构造函数参数是一个函数,该函数的两个参数分别是resolvereject,它们是两个函数,由javascript提供,不用自己部署。

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

promise.then(function(value){
    //success
    }, function(error){ // 这个函数是可选的,不一定要提供
    //failure
})

使用Promise的栗子:Promise包装了一个图片加载的异步操作。如果加载成功,就调用resolve方法,否则就调用reject方法。

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

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

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

        image.src = url
    })
}

用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 xhr = new XMLHttpRequest();
        xhr.open(‘GET‘, url);
        xhr.onreadystatechange = handler;
        xhr.responseType = ‘json‘;
        xhr.setRequestHeader(‘Accept‘, ‘application/json‘);
        xhr.send();
    });
    return promise;
}

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

getJSON内部,resolve函数和reject函数调用时,都带有参数。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个Promise实例。

下图一、promise内部调用reject函数之后,在then方法内第二个参数函数里面输出抛出的错误。

下图二、(同上)虽然在最后有catch语句,但是不会被调用。

下图三、promise内部调用reject函数之后,没有then方法的第二个参数,那么会在catch方法里面输出抛出的错误。

var promise = new Promise(function(resolve, reject){
    reject(new Error(‘123‘))
}).then(function(data){
    console.log(data)
},function(error){
    console.log(1);
    console.log(error)
})

//输出:
1
Error: 123
var promise = new Promise(function(resolve, reject){
    reject(new Error(‘123‘))
}).then(function(data){
    console.log(data)
},function(error){
    console.log(1);
    console.log(error)
}).catch(function(err){
    console.log(2);
    console.log(err)
})

//输出:
1
Error: 123
var promise = new Promise(function(resolve, reject){
    reject(new Error(‘123‘))
}).then(function(data){
    console.log(data)
}).catch(function(err){
    console.log(2);
    console.log(err)
})

//输出:
2
Error: 123

如果在then方法里面的第二次参数里面return new promise,那么会在catch里面捕获错误

var promise = new Promise(function(resolve, reject){
    reject(new Error(‘123‘))
}).then(function(data){
    console.log(data)
},function(error){
    console.log(1);
    return new Promise(function(resolve, reject){reject(new Error(‘abc‘))})
}).catch(function(err){
    console.log(2);
    console.log(err)
})
//输出:
1
2
Error: abc

catch方法并没有捕获到then方法内的new Error错误

var promise = new Promise(function(resolve, reject){
    resolve(‘123‘)
}).then(function(data){
    console.log(data)
    console.log(new Error(‘error‘));
},function(error){
    console.log(1);
    
}).catch(function(err){
    console.log(2);
    console.log(err)
})

//输出
123
Error: error

并没有在catch方法里面输出error。

var promise = new Promise(function(resolve, reject){
    resolve(‘123‘)
}).then(function(data){
    console.log(data)
    return new Promise((resolve, reject)=>{new Error(‘error‘)});
},function(error){
    console.log(1);
    
}).catch(function(err){
    console.log(2);
    console.log(err)
})

//输出
123

只有promise里面调用resolve、reject函数才会在then方法里面有输出

var promise = new Promise(function(resolve, reject){
    resolve(‘123‘)
}).then(function(data){
    console.log(data)
    return new Promise((resolve, reject)=>{resolve(new Error(‘error‘))});
},function(error){
    console.log(1);
    
}).then(function(data){console.log(data)})
.catch(function(err){
    console.log(2);
    console.log(err)
})

//输出:
123
Error: error
var promise = new Promise(function(resolve, reject){
    resolve(‘123‘)
}).then(function(data){
    console.log(data)
    return new Promise((resolve, reject)=>{reject(new Error(‘error‘))});
},function(error){
    console.log(1);
    
}).then(function(data){console.log(data)})
.catch(function(err){
    console.log(2);
    console.log(err)
})

//输出:
123
2
Error: error

 

Promise.race()

Promise.all()

async()/await()

yuansheng js

webassemble

 

以上是关于Promise的主要内容,如果未能解决你的问题,请参考以下文章

前端面试题之手写promise

什么时候然后从Promise.all()的子句运行?

Typescript编译器无法从Promise resolve调用中推断类型

前端片段整理

在 Promise 中包装 Auth0 的 parseHash 函数

在javascript承诺中执行的顺序是什么