美文网首页
ES6(Promise)

ES6(Promise)

作者: 陈裔松的技术博客 | 来源:发表于2018-12-19 08:27 被阅读0次

Promise的概念

Promise对象用于表示一个异步操作的最终状态(完成或失败)以及其返回的值 --- MDN

回调与Promise

模拟场景

实现一个功能:以1秒的间隔依次显示1,2,3,4

传统回调
// 方式1:传统回调方式
function f(cb) {
    setTimeout(function () {
        cb && cb();
    }, 1000);
}

f(function () {
    // 第一层回调中的处理
    console.log(1);

    f(function () {
        // 第二层回调中的处理
        console.log(2);

        f(function () {
            // 第三层回调中的处理
            console.log(3);

            f(function () {
                // 第四层回调中的处理
                console.log(4);
            });
        });
    });
});

// 执行结果:以1秒的间隔依次显示1,2,3,4

这里只是举个例子,所有每一次层的处理都很简单,只是显示一个数字。
在实际业务中,每一次层的处理会很复杂。然后如果有需求想要交换下第二层和第三层的处理,该怎么弄?即使对业务逻辑很清楚,这事情处理起来也简直就是地狱。。甚至如果还有5678层呢?

Promise
// 方式2:Promise方式
function f(cb) {
    // 说明
    // 返回一个Promise实例
    // 参数resolve代表成功时候要做的事情
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, 1000);
    });
}

// 说明
// 由于f返回的是一个Promise实例,所以拥有then方法
// then方法里就是实际要做的事情
f()
    .then(() => {
        console.log(1);
        return f();  // 这里需要返回f(),这样就能继续then下去了
    })
    .then(() => {
        console.log(2);
        return f();  // 这里需要返回f(),这样就能继续then下去了
    })
    .then(() => {
        console.log(3);
        return f();  // 这里需要返回f(),这样就能继续then下去了
    })
    .then(() => {
        console.log(4);
    })
// 执行结果:以1秒的间隔依次显示1,2,3,4
// 这和传统回调方式的结果是一样的

可以看到,以Promise的方式处理这个问题,不是一层嵌一层的样子了,而是一步做完再接着做下一步。是不是比传统的回调方式好理解很多?交换某两个处理的顺序也会很方便。
新事物的出现一定有它的理由和好处,Promise就是为了解决回调地狱而出现的。非常友好,值得我们拥抱它。

错误处理

then(resolve, reject)
// then方法中的第二个回调reject,就是失败时候做的事情
function f(a) {
    return new Promise((resolve, reject) => {
        if (a) {
            resolve();
        } else {
            reject();
        }
    })
}

f(false)
    .then(() => {
        console.log('我是成功时候的处理');
    }, () => {
        console.log('我是失败时候的处理');
    });

// 执行结果:我是失败时候的处理
catch
// 使用实例的catch方法,可以捕获错误
function f(a) {
    return new Promise((resolve, reject) => {
        if (a) {
            resolve();
        } else {
            reject();
        }
    })
}

f(false)
    .then(() => {
        // 这里不会执行到
        console.log('我是成功时候的处理');
        return f(false);
    })
    .catch(()=>{
        console.log('我是失败时候的处理');
    });

// 执行结果:我是失败时候的处理
finally
// 不伦成功还是失败,finally中的内容一定会执行
// 跟最终的处理一起执行
function f(a) {
    return new Promise((resolve, reject) => {
        if (a) {
            resolve();
        } else {
            reject();
        }
    })
}

f(false)
    .then(() => {
        // 这里不会执行到
        console.log('我是成功时候的处理');
        return f(false);
    })
    .catch(() => {
        console.log('我是失败时候的处理');
        return f(true);
    })
    .finally(() => {
        console.log('finally');
    });

// 执行结果:我是失败时候的处理 finally

Promise的三种状态

  • pending(进行中)
  • fulfilled(成功)
  • rejected(失败)

状态的改变不可逆,一旦决议就不能再修改。且只有以下两种改变形式。
pending(进行中) => fulfilled(成功)
pending(进行中) => rejected(失败)

Promise方法

Promise.all()

Promise.all方法可以把多个promise实例,包装成一个新的promise实例。
Promise.all([promise1,promise2,promise3]):Promise

特点1:当promise1,promise2,promise3都成功的时候,Promise.all就决议为成功,且返回由promise1/promise2/promise3的结果组成的数组。

// 模拟需要多个请求的数据,才能进行下一步操作的情况
function getData1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第一条数据加载成功!');
            resolve('data1');
        }, 1000);
    });
}

function getData2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第二条数据加载成功!');
            resolve('data2');
        }, 1000);
    });
}

function getData3() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第三条数据加载成功!');
            resolve('data3');
        }, 2000);
    });
}

let p = Promise.all([getData1(), getData2(), getData3()]);
p.then(arr => {
    console.log(arr);
});

// 执行结果:
// 1s之后显示:"第一条数据加载成功!" 和 "第二条数据加载成功!"
// 2s之后显示:"第三条数据加载成功!"
// p.then中的arr为 ["data1", "data2", "data3"]

特点2:当promise1,promise2,promise3之中有一个失败的时候,Promise.all就决议为失败,且返回失败的信息。

// 模拟需要多个请求的数据,才能进行下一步操作的情况
function getData1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第一条数据加载成功!');
            resolve('data1');
        }, 1000);
    });
}

function getData2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第二条数据加载成功!');
            resolve('data2');
        }, 1000);
    });
}

function getData3() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第三条数据加载失败!');
            reject('err data3');  // !!注意这里调用的是reject,表示失败
        }, 2000);
    });
}

let p = Promise.all([getData1(), getData2(), getData3()]);
p
    .then(arr => {
        // 这里永远不会执行到
        console.log(arr);
    })
    .catch(err => {
        console.log(err);
    });

// 执行结果:
// 1s之后显示:"第一条数据加载成功!" 和 "第二条数据加载成功!"
// 2s之后显示:"第三条数据加载失败!"
// p.catch中的err为 "err data3"

特点3:当Promise.all([])的时候,Promise.all就直接决议为成功。

let p = Promise.all([]);

p
    .then(arr => {
        console.log("成功");
    })
    .catch(err => {
        console.log("失败");
    });

// 执行结果:成功
Promise.race()

顾名思义,race是竞赛的意思。
所以Promise.race方法,是把多个promise实例中,最先成功或失败的结果拿出来。
Promise.race([promise1,promise2,promise3]):Promise

  • 成功的情况
function getData1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第一条数据加载成功!');
            resolve('data1');
        }, 1000);
    });
}

function getData2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第二条数据加载成功!');
            resolve('data2');
        }, 1500);
    });
}

function getData3() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第三条数据加载成功!');
            resolve('data3');
        }, 500);
    });
}

let p = Promise.race([getData1(), getData2(), getData3()]);

p.then(data => {
    console.log(data);  // data3
});
// 执行结果:
// 0.5s之后显示:"第三条数据加载成功!"
// p.then中的data为 "data3"
// 1s之后显示:"第一条数据加载成功!"
// 1.5s之后显示:"第二条数据加载成功!"
  • 失败的情况
function getData1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第一条数据加载成功!');
            resolve('data1');
        }, 1000);
    });
}

function getData2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第二条数据加载成功!');
            resolve('data2');
        }, 1500);
    });
}

function getData3() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('第三条数据加载失败!');
            reject('err data3');
        }, 500);
    });
}

let p = Promise.race([getData1(), getData2(), getData3()]);

p.then(data => {
    // 这里不会被执行到
    console.log(data);
}).catch(data => {
    console.log(data);  // err data3
});
// 执行结果:
// 0.5s之后显示:"第三条数据加载失败!"
// p.then中的data为 "err data3"
// 1s之后显示:"第一条数据加载成功!"
// 1.5s之后显示:"第二条数据加载成功!"
Promise.resolve()

常用来生成已经被决议为成功的Promise实例

function f(a) {
    return new Promise((resolve, reject) => {
        if (a) {
            resolve();
        } else {
            reject();
        }
    })
}

f(true)
    .then(() => {
        console.log('处理1');
        return Promise.resolve();  // 这里就相当于  return f(true);
    })
    .then(() => {
        console.log('处理2');
    })
    .catch(() => {
        console.log('错误');
    });

// 执行结果:处理1 处理2
Promise.reject()

常用来生成已经被决议为失败的Promise实例

function f(a) {
    return new Promise((resolve, reject) => {
        if (a) {
            resolve();
        } else {
            reject();
        }
    })
}

f(true)
    .then(() => {
        console.log('处理1');
        return Promise.reject();  // 这里就相当于 return f(false)
    })
    .then(() => {
        console.log('处理2');
    })
    .catch(() => {
        console.log('错误');
    });

// 执行结果:处理1 错误

相关文章

网友评论

      本文标题:ES6(Promise)

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