目录:
  • 什么是promise
  • 为什么使用promise
  • promise用法
    • new Promise
    • resolve()&rejct()
    • then()
  • then链式调用
  • catch作用
  • promise方法
    • Promise.all()
    • Promise.race()
    • finally()

什么是Promise

它是异步执行的一种解决方案。它只有三种状态:等待、成功和失败。

为什么要使用Promise

在执行异步操作时,往往是通过回调方式进行的。但一般来说,回调又会有好多层,例如:

操作1(function () {
    // 请求成功
    操作2(function () {
        // 请求成功
        操作3(function () {
            // .......
        })
    })
})

在这种请求完成后再进行请求的场景下就不得不使用嵌套,这就陷入了回调地狱。
Promise以链式请求的形式解决了这一问题。下面我们来看一下。

Promise用法:

不需要懂代码是什么意思,请看解释。

let p = new Promise(function (resolove, reject) {
    let a = 10;
    setTimeout(() => {
        if (a > 0) {
            resolve("Yes!");
        } else {
            reject("No!")
        }
    }, 1000)
})
p.then(function (result) {
    console.log(result);//yes
}, function (result) {
    console.log(result);
}

解释:

  • new Promise创建了一个Promise对象,并且参数是一个回调函数,回调函数中有两个参数。
  • resolve()方法表示成功状态,将Promise的状态由pending(等待)变为resolve(成功)。
  • reject()方法表示失败状态,将Promise的状态由pending(等待)变为rejected(失败)。
  • thenPromise的方法,也是链式调用的关键。

我们从上述代码中可以看出,异步执行不再是回调形式,而是将结果给Promisethen方法,即将数据从回调函数中拿出来。

new Promise

promist实例可以看作是监听了请求,在请求发出后的状态是等待,进而表现为成功或者失败。而请求后所有的操作放在了then方法里。因为promise中只是让我们知道了它的状态是等待成功或者失败,并没有进行操作。

resolve()&reject()

对于这两个方法是用来改变promise状态的,并且状态一旦改变就不能被更改。比如在执行完resolve()方法后状态变为resolved,那这个对象的最终状态就是这个。

then

then充当回调,并接收两个函数,第一个函数始终表示为成功状态,第二个函数始终表示为失败状态。并且参数result表示结果,是由resolve()reject()传进来的。

但问题又来了,我们想要进行多个请求时怎么写?

let p = new Promise(function (resolve, reject) {
    let a = 10;
    setTimeout(() => {
        if (a > 0) {
            resolve("Yes!");
            let b = 10;
            setTimeout(() => {
                //.....
            }, 1000)
        } else {
            reject("No!")
        }
    }, 1000)
})
p.then(function (result) {
console.log(result);//yes
}, function (result) {
    console.log(result);
}

这么写吗?在第一次状态为成功态时,请求第二次?那这样不就再次陷入回调地狱了吗?

then链式调用:

上文我们已经提过,then可以接收两个函数,当然我们还可以再每一个then中创建新的promise然后将这个promise返回,再交给then处理。

let p = new Promise(function (resolve, reject) {
    let a = 10;
    setTimeout(() => {
        if (a > 0) {
            resolve("Yes!");
        } else {
            reject("No!")
        }
    }, 1000)
}
p.then(function (result) {
    console.log(result);//yes
    return p = new Promise(functio(resolve,reject) {
        let b = -10;
        setTimeout(() => {
            if (b > 0) {
                resolve("Yes!");
            } else {
                reject("No!");
            }
        })
    })
}, function (result) {
    console.log(result);
})
    .then(function (result) {
        console.log(result);
    }, function (result) {
        console.log(result);  // No!
    })

就像这样,在第一次请求完毕返回一个新的promise。这样写虽然比较乱,但解决了回调地狱问题。在第一次请求完毕后,创建新的对象并返回。然后给then处理,所以就形成了then的链式调用。

then链式调用美化


function r1() {
    return new Promise(function (resolve, reject) {
        let a = 10;
        setTimeout(() => {
            if (a > 0) {
                resolve("Yes!");
            } else {
                reject("No!")
            }
        }, 1000)
    })
}
function r2() {
    return new Promise(function (resolve, reject) {
        let b = -10;
        setTimeout(() => {
            if (b > 0) {
                resolve("Yes!");
            } else {
                reject("No!");
            }
        })
    })
}
let p = r1();
p.then(function (result) {
    console.log(result);//yes
    return r2();
}, function (result) {
    console.log(result);
}).then(function (result) {
    console.log(result);
}, function (result) {
    console.log(result);  //No
})

既然我们已经明白怎样进行链式调用,那上方代码就是美化都的结果。将请求抽离封装,返回一个状态。并在then方法中链式调用。
虽然会失败,但程序不会停止执行。

catch()

catch()其实也是处理reject()。处理报错时使用的try-catch语句和这里的catch()差不多。

既然reject()表示失败状态,并且我想要的结果是在前一个请求成功的基础上再进行下一次请求,那我直接将错误收集起来,如果有一个报错,就停止执行。

function r1() {
    return new Promise(function (resolve, reject) {
        let a = 10;
        setTimeout(() => {
            if (a > 0) {
                resolve("Yes!");
            } else {
                reject("No!")
            }
        }, 1000)
    })
}
function r2() {
    return new Promise(function (resolve, reject) {
        let b = -10;
        setTimeout(() => {
            if (b > 0) {
                resolve("Yes!");
            } else {
                reject("No!");
            }
        })
    })
}
let p = r1();
p.
    then(function (result) {
        console.log(result);//yes
        return r2();
    }).
    then(function (result) {
        console.log(result);  
        return r1();
    }).
    then(function (result) {
        console.log(result);
    })
    .catch(function (result) {
        console.log(result);//no

在第二次请求失败后就会结束执行。

Promise方法:

Promise.all():同时监听多个请求,并参数是数组,数组中每一项都是promise实例。若每一项都是成功状态,这个新的promise才会成功,否则失败状态。
//r1、r2在上面代码中已经定义。
let p = Promise.all([r1(), r2()]);
p.then(function (result) {
    console.log(result)
}).catch(function (result) {
    console.log(result) //No
})
Promise.race():同时发送多个请求 但是它是跟随最早发生变化的那个Promise。假设最先改变的是r2变成rejected状态,那返回的就是失败状态。
//r1、r2在上面代码中已经定义。
let p = Promise.race([r1(), r2()]);
p.then(function (result) {
    console.log(result)
}).catch(function (result) {
    console.log(result)
})
finally():不论何时添加都可以执行,和switch中的defaulttry-catch-finally中的finally。无论失败成功,finally都在那里。
更多内容请看:IFTS