Promise 扩展学习

上一篇文章学习了 Promise 的基本使用方法后,这一章进行拓展练习。

使用 reject 而不是 throw

Promise 的构造函数和被 then 方法调用的函数基本上是在 try...catch 代码块中执行的,所以在这些代码中及时使用 throw ,程序本省也不会因为异常而终止。

如果在 Promise 中使用 throw ,会被 try...catch 捕获到,最终 promise 对象也会变为 rejected 状态。

var promise = new Promise((resolve, reject) => {
    throw new Error("message");
}).catch(error => {
    console.error(error);
})

上述代码运行也是可以的,但如果想把 promise 对象的状态设置为 rejected ,使用 reject 方法更加合适。

var promise = new Promise((resolve, reject) => {
    reject(new Error("message"))
}).catch(error => {
    console.error(error);
})

这样写,就无需调用 throw 方法抛出错误,而是使用 reject 函数传递 Error 。而且使用 throw 抛出错误,无法判断是我们主动跑出来的还是异常引起的。

而且 then 方法的第二个参数可以处理错误捕获,能连续处理多个异步而不影响程序的正常运行。

总结

  • 使用 rejectthrow 安全;
  • then 方法中能够使用 reject 方法。

使用 Promise 进行顺序处理

var request = {
    comment: function getComment() {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve("comment")
            }, 500);
        });
    },
    people: function getPeople() {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve("people")
            }, 200);
        });
    }
}
function main(tasks) {
    // 异步函数的返回结果无法使用普通的 return 返回出去,因为它是异步的,只能通过 then 方法传递结果
    function recordValue (results, value) {
        results.push(value);
        return results;
    }
    var pushValue = recordValue.bind(null, []); // 每次都是一个新的promise,而且 results 是在闭包里面的,无需指定 this
    
    // 使用普通 for 循环
    // var promise = Promise.resolve();
    // for (var i = 0; i < tasks.length; i++) {
    //     var task = tasks[i];
    //     promise = promise.then(task).then(pushValue); // 将所有任务使用 promise chain 串联起来,因为每次调用 then 方法都会返回一个新的 promise 对象
    // }
    // return promise;

    // 使用 reduce 方法
    return tasks.reduce(function (promise, task) {
        return promise.then(task).then(pushValue);
    }, Promise.resolve());
}
main([request.comment, request.people]).then(res => {
    console.log(res);
}).catch(err => {
    console.error(err);
})

多个 Promise 对象并发处理

在 js 中,可能会存在同时发起 N 个请求的场景,如若超出最大限制数,则等待;如若其中一个完成,添加请求。等到所有请求结束后,执行回调。

function wait (arr, max, callback) {
        var i = 0,
            fetchArr = []; // 任务队列
        function toFetch () {
            if (i === arr.length) {
                return Promise.resolve();
            }
            var task = arr[i++]();
            fetchArr.push(task);
            // 执行完后,从任务队列中删除
            task.then(() => {fetchArr.splice(fetchArr.indexOf(task), 1)});
            // 如果任务队列到达上限
            var p = Promise.resolve();
            if (fetchArr.length >= max) {
                p = Promise.race(fetchArr);
            }
            return p.then(() => toFetch());
        }
        toFetch().then(() => Promise.all(fetchArr)).then(() => {
            callback(); 
        });
}
var request = [
    () => new Promise(resolve => {
        setTimeout(() => {
            console.log(1);
            resolve(1)
        }, 500)
    }),
    () => new Promise(resolve => {
        setTimeout(() => {
            console.log(2);
            resolve(2)
        }, 1000)
    }),
    () => new Promise(resolve => {
        setTimeout(() => {
            console.log(3);
            resolve(3)
        }, 200)
    }),
    () => new Promise(resolve => {
        setTimeout(() => {
            console.log(4);
            resolve(4)
        }, 700)
    }),
    () => new Promise(resolve => {
        setTimeout(() => {
            console.log(5);
            resolve(5)
        }, 1000)
    })
];
wait(request, 2, function () {
    console.log("end");
});
// 1
// 3
// 4
// 2
// 5
// end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值