前端异步解决方案-3(Promise)

2次阅读

共计 3665 个字符,预计需要花费 10 分钟才能阅读完成。

又有好些天没有动笔了,这几天一直在断断续续的学习 Promise 和 generator,今天终于能够把着两个玩意结合起来了解决异步问题了。今天我先把 promise 相关的用法和对异步的处理分享给大家。老样子,还是先模拟一个 Promise。
// 咳咳这样就实现了嘛
let MyPromise = Promise;
开个玩笑,其实这两天我也一直在看 Promise 的实现,但是还是没有怎么理解。所以 Promise 的代码实现我暂时先放一放,等我完全理解再来新开一篇分享。这里先给大家推荐几篇我觉得比较好的 Promise 实现的博客,想要学习的小伙伴可以先到那边一睹为快,当然等我更新了之后大家还是要来给我文章点赞的哈。彻底理解 Promise 对象——用 es5 语法实现一个自己的 Promise(上篇) 这一篇文章用的 es5 的语法,对 es6 不是很熟悉的同学可以用这篇文章顶一下 Promise 实现原理(附源码)这一篇呢是用到了 class 的,所以需要大家对 es6 有所了解,也是一篇好文章
接下来我介绍一下 Promise 最常用的几个部分:

首先先介绍最简单的只有一个 Promise 对象的用法
//Promise() 接收一个函数,并且在创建这个 Promise 对象的同时,接收的这个函数就会被立刻执行
var promise = new Promise(function (resolve, reject) {
//resolve 用来接收成功的返回,reject 用来接收失败的返回
setTimeout(function () {
// 这里我们生成一个随机数,并在接下来根据这个随机数的大小来判断这个异步是否成功
let num = Math.random();
if (num > 0.8) {
// 接收失败的原因
console.log(“reject”)
reject(num + “ 大于 0.8,这次异步操作失败了 ”)
} else {
// 接收成功的数据
console.log(“resolve”)
resolve(num + “ 小于 0.8,这次异步操作成功了 ”)
}
}, 100)
});
console.log(“ 一个 Promise 对象生成了 ”);
//Promise 对象的.then() 方法接收两个回调,第一个为成功回调,第二个为失败回调
// 这两个回调会在上面的 resolve 或者 reject 函数生效后被调用
promise.then(function (data) {
// 这个函数会在上面的 resolve 函数被调用后生效, 这里的 data 就是上面 resolve() 中接收的值
console.log(data)
}, function (err) {
/// 这个函数会在上面的 reject 函数被调用后生效, 这里的 err 就是上面 reject() 中接收的值
console.error(err)
});
console.log(“promise 的.then 方法被调用了 ”)
大家可以按 F12 唤起控制台,然后把这段代码运行几次。看看会有什么结果;多运行几次以后,大家应该可以看到这两类结果:其中的 undefind 是 console.log(“promise 的.then 方法被调用了 ”) 这行代码的返回,大家可以不用关注。在这里可以看到不论是成功的结果还是失败的结果都是在定时器执行后再打印出来的。这种写法可以帮助我们实现简单的异步编程。

接下介绍多个 Promise 对象同时使用的用法,先介绍最常见的.then() 链式调用的方法
// 用来快速生成一个 Promise 对象,接收一个日志列表,不论成功还是失败都会往日志列表中添加一条日志
function promise(log) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
log = log || [];
// 和上次的例子一样,利用随机数来随机失败和成功
let num = Math.random();
if (num > 0.5) {
log.push(num + “ 大于 0.5,这次异步操作失败了 ”);
reject(log)
} else {
log.push(num + “ 小于 0.5,这次异步操作成功了 ”);
resolve(log)
}
}, 100)
})
}
.then() 中返回了 Promise 对象的情况
var promise1 = promise();
//promise1.then() 方法会返回一个 Promise 对象
// 如果我们在.then() 生效的那个 !!! 回调方法!!! 中有返回一个 Promise 对象的话,该对象会被 !!!.then() 方法!!! 返回

// 先看返回了 Promise 对象的方式
promise1.then(function (data) {
console.log(data);
return promise(data)
}, function (err) {
console.error(err);
return promise(err)
}).then(function (data) {
console.log(data)
}, function (err) {
console.error(err)
});
这段代码运行后一共会有四种结果:两次都成功 两次都失败 第一次失败,第二次成功 第一次成功,第二次失败
通过这种方法我们可以用比较清晰的方式来书写我们的异步代码。特别是多个异步操作嵌套的时候,可以链式调用.then() 来实现,这样的代码看起来逻辑更清晰;刚刚看完了返回了 Promise 对象的场景,再来看看没有返回 Promise 的场景
// 如果我们没有返回 Promise 对象,.then() 就会将我们返回的东西包装成一个 Promise 对象(没有返回就相当于返回了 undefined)
// 可以等同于我们写了 return new Promise((resolve,reject)=>{resolve(/* 原先的返回值 */)})
promise1.then(function (data) {
console.log(data);
return data;
}, function (err) {
console.error(err);
return err;
}).then(function (data) {
console.log(data)
}, function (err) {
// 这里是永远不会被触发的,原因是上一个.then() 返回的是 new Promise((resolve,reject)=>{resolve(/* 原先的返回值 */)})
// 返回的 Promise 对象的 reject 方法永远都不会被触发,所以这个里也就永远都不会触发了
console.error(err)
});
讲解都写在注释里面了,接下里我就贴运行图吧,这段代码会运行出以下两类结果:

需要所有的请求都返回后才可以执行某个动作
// 改造 promise, 让其可以接收一个定时器等待时间参数
function promise(log, time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
log = log || [];
// 和上次的例子一样,利用随机数来随机失败和成功
let num = Math.random();
if (num > 0.5) {
log.push(“ 等待时长 ” + time + “,” + num + “ 大于 0.5,这次异步操作失败了 ”);
console.error(log);
reject(log)
} else {
log.push(“ 等待时长 ” + time + “,” + num + “ 小于 0.5,这次异步操作成功了 ”);
console.log(log);
resolve(log)
}
}, time)
})
}
//Promise.all() 可以接收一个 Promise 对象的数组,返回一个 Promise 对象
// 该 Promise 对象会在数组中所有 Promise 成功返回后执行成功回调,在任意一个 Promise 失败后立刻执行失败回调
var promise1 = promise(null, 10), promise2 = promise(null, 100),
promise3 = Promise.all([promise1, promise2]);
promise3.then((data) => {
// 这里的 data 为 promise1, 和 promise2 的返回值的数组
console.log(“promise3”, data)
}, (err, err2) => {
// 报错信息
console.error(“promise3”, err)
});
这段代码一共有四种可能的结果 如果两次都成功的话 如果两次都成的话,promise3 会执行成功回调,并且回调中的 data 就是 promise1 和 promise2 返回值的数组(数组顺序和.all() 中的顺序一致)任意一个 promise 失败的话,promise3 会立刻执行失败回调,并且回调中的 err 就是失败的那个 promise 在 reject 中返回的值

文章写到这里,我认为 Promise 常用的一些用法都已经讲完了,更详细的 Promise 的教程请参考 MDN 中对 promise 的讲解

正文完
 0