Promise

57 阅读2分钟

1.提出问题

1-1.问题的产生

  • 模拟一次网络请求(异步操作),本想返回成功或失败,结果得到undefined
function req(url) {
    setTimeout(() => {
        if (url === 'favo.ico') {
            return '成功'
        } else {
            return '失败'
        }
    }, 3000);
}

const res = req('favo.ico')
console.log(res); // undefined

1-2 最初的解决方法

  • 思路:传入两个回调,一个成功一个失败
  • 缺点:太过灵活,没有规范,有需要阅读源码、传参不便等问题
function req(url, suc, err) {
    setTimeout(() => {
        if (url === "favo.ico") {
            suc()
        } else {
            err()
        }
    }, 3000)
}

function suc() {
    console.log("请求成功")
}

function err() {
    console.log("请求失败")
}

req("favo.icon", suc, err)

2.promise

2-1.executor立即执行

  • newpromise中传递一个回调函数executor立即执行,传入两个参数回调函数resolve/reject
  • 执行resolve,回调.then
  • 执行reject,回调.catch
const pro = new Promise((resolve, reject) => {
    console.log('立即执行');
})

2-2.将最初的解决方法重构

function pro(url) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (url.includes('a')) {
                resolve(url)
            } else {
                reject('err')
            }
        }, 1000);
    })
}

// 第一种写法
pro('aaa').then(res => console.log(res), (rej) => console.log(rej))

// 第二种写法
pro('aaa').then(res => console.log(res)).catch((rej) => console.log(rej))
  • 解读:

    • newpromise时,传入的executor会被promise自动执行立即执行
    • 成功执行resolve,失败执行reject
  • 异常处理:

    • .then中传入两个回调,第一个resolve(即fullfilled),第二个reject
    • .catch捕获
  • 好处:

    • 统一规范,增强阅读性
    • 小幅度减少回调地狱

2-3.promise的状态

  • 状态

    • pending
    • fullfilled(resolve)
    • rejected
  • 注:状态从待定转为其他,就不能再改变了

const pro = new Promise((res, rej) => {
    rej('err')
    res('suc')
})

pro.then(res => console.log(res)).catch(rej => console.log(rej))
// err

2-4.resolve的不同值

  • 1.只能传一个参数,传一个普通值或对象时,作为then的回调参数
const pro = new Promise((resolve, reject) => {
  resolve({ name: "a", age: "b" });
});
pro.then((res) => console.log(res)); 
// { name: "a", age: "b" }
  • 2.promise中传入promise,内部promise决定外部promise的状态
const pro = new Promise((resolve, reject) => {
    resolve(
        new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("aaa"); // aaa
                // reject("bbb");
            }, 500);
        })
    );
});

pro.then((res) => console.log(res));
// aaa
  • 3.promsie中传入对象,且对象实现了then方法,根据then方法中的调用决定promise状态==>thenable模式
const pro = new Promise((resolve, reject) => {
    resolve({
        then(res, rej) {
            res("成功");
        },
    });
});


pro.then((res) => console.log(res));
// 成功

2.5.promise的实例方法

2.5.1.then

2.5.1.1.参数

  • 两个参数,一个成功回调,一个失败回调
const pro = new Promise((resolve, reject) => {
  resolve("aaa");
  reject("bbb");
});
pro.then(
  (res) => console.log(res, "1"),
  (rej) => console.log(rej, "2")
);
  • 只捕获错误,第一位写null或''
const pro = new Promise((resolve, reject) => {
  reject("bbb");
});
pro.then("", (rej) => console.log(rej, "2"));

2.5.1.2.多次调用,多次输出

2.5.1.3.!then是有返回值的,then的返回值是promise,

未完~