# Promise 方法

Promise 中的执行函数是同步进行的,但是里面存在着异步操作,在异步操作结束后会调用 resolve 方法,或者中途遇到错误调用 reject 方法,这两者都是作为微任务进入到 EventLoop 中。

下面的例子,来了解同步和异步

console.log(1)
let promiseDemo = new Promise((resolve, reject) => {
    console.log(2)
    let random = Math.random()
    if (random >= 0.2) {
        resolve('success')
        console.log(3)
    } else {
        reject('failed')
        console.log(3)
    }   
})
console.log(8)
async function test() {
    console.log(4)
    let result = await promiseDemo
    return result
}
setTimeout(() => {
    console.log(7)
}, 0)
test().then(result => {
    console.log(5)
}).catch((result) => {
    console.log(5)
})

console.log(6)

// 1 2 3 8 4 6 7 5

# then()

用于成功时的回调函数。

# catch()

用于指定发生错误时的回调函数。

一般来说,不要在then()方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。

// bad
promise
    .then(function(data) {
        // success
    }, function(err) {
        // error
    });

// good
promise
    .then(function(data) {
        // success
    })
    .catch(function(err) {
        // error
    });

# finally()

finally()方法用于指定不管Promise对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

finally方法的回调函数不接受任何参数,方法里面的操作,是与状态无关的,不依赖于Promise的执行结果。

promise
    .then(result => {···})
    .catch(error => {···})
    .finally(() => {···});

promise
    .finally(() => {
    // 语句
    });

// 等同于
promise
    .then(
        result => {
            // 语句
            return result;
        },
        error => {
            // 语句
            throw error;
        }
    );

上面代码中,如果不使用finally方法,同样的语句需要为成功和失败两种情况各写一次。有了finally方法,则只需要写一次。

# all()

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

只有Promise1Promise2Promise3的状态都变成fulfilledp的状态才会变成fulfilled,此时Promise1Promise2Promise3的返回值组成一个数组,传递给p的回调函数。

只要Promise1Promise2Promise3之中有一个被rejected,p的状态才会变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

let Promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        var num = Math.ceil(Math.random()*10); //生成1-10的随机数
        if(num <= 5){
            resolve(num);
        }
        else{
            reject('数字太大了');
        }
    }, 2000)
})
let Promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        var num = Math.ceil(Math.random()*10); //生成1-10的随机数
        if(num <= 5){
            resolve(num);
        }
        else{
            reject('数字太大了');
        }
    }, 2000)
})
let Promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        var num = Math.ceil(Math.random()*10); //生成1-10的随机数
        if(num <= 5){
            resolve(num);
        }
        else{
            reject('数字太大了');
        }
    }, 2000)
})

let p = Promise.all([Promise1, Promise2, Promise3])

p.then((res) => {
    // 三个都成功则成功  
    console.log('resolved', res)
}).catch((err) => {
    // 只要有失败,则失败 
    console.log('rejectd', err)
})

适合使用的场景,在所有异步方法都执行完毕后,再执行某一方法。

# race()

接收数组,方法返回一个promise,一旦迭代器中的某个promise解决或拒绝,返回的promise就会解决或拒绝。

race就是竞争的意思,数组内的Promise实例,谁执行的快,就返回谁的执行结果,不管是成功还是失败

var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "one"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "two"); 
});

Promise.race([p1, p2]).then(function(value) {
    console.log(value); // "two"
    // 两个都完成,但 p2 更快
});

var p3 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "three");
});
var p4 = new Promise(function(resolve, reject) { 
    setTimeout(reject, 500, "four"); 
});

Promise.race([p3, p4]).then(function(value) {
    // p3 更快,所以它完成了              
    console.log(value); // "three"
}, function(reason) {
    // 未被调用
});

var p5 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "five"); 
});
var p6 = new Promise(function(resolve, reject) { 
    setTimeout(reject, 100, "six");
});

Promise.race([p5, p6]).then(function(value) {
    // 未被调用             
}, function(reason) {
    console.log(reason); // "six" p6 更快,所以它失败了
});

# allSettled()

接受一组 Promise 实例作为参数,包装成一个新的Promise实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。该方法由 ES2020 引入。

该方法返回的新的Promise实例,一旦结束,状态总是fulfilled,不会变成rejected

状态变成fulfilled后,Promise的监听函数接收到的参数是一个数组,每个成员对应一个传入Promise.allSettled()Promise实例。

const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);

const allSettledPromise = Promise.allSettled([resolved, rejected]);

allSettledPromise.then((results) => {
  console.log(results);  
});
// [{status: "fulfilled", value: 42}, {status: "rejected", reason: -1}]

# 参考