Promise

由于js的语言特性(用户交互)和工作环境(浏览器脚本),决定了它是单线程工作,所以两段脚本不能同时运行,但为了实现功能,所以人们使用了事件和回调来初步解决这个问题,例如(addEventListener),但这也带来了严重的回调问题,非常容易陷入回调地狱的困恼,

由于这个问题。js发展至今,社区提出了promise(承若)标准,被es6写入了语言标准中,统一了它的用法,并在原生中提供了标准的Promise对象

让我们先来实例化一个标准的promise对象:

	//实例化一个promise对象,这个对象有两个参数(resolve-决定,reject-拒绝)
let promise = new Promise((resolve,reject)=>{
//延时3s,把promise的状态改为resolve-决定
setTimeout(function(){
resolve('666')
},3000)
})
//每个实例都有then()方法,用来获取其值或原因。
//then(onFulfilled, onRejected)
//成功的回调,失败的回调
promise.then(data=>{
console.log(data)
},err=>{
console.error(err)
}).then()

同时promise还可以多次调用then()方法,也可以在resolve中继续抛出一个新的promise 例:

	promise.then(function(data){
console.log('data2=',data);
},function(err){
console.log('err2=',err);
});

或者:

	let promise2 = promise.then(function(data){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve(data + '777' );
},1000);
});
});

当然还有常见的all(),catch(),resolve(),reject()等等一些方法,而这些方法都是按照Promise/A+规范规定的 (详情

我们现在就按照这个规范来实现一个属于我们自己的promise

首先我们先定义出这个类:

// executor是一个执行函数,在实例化的时候被传入。这个函数会执行两个被传入的状态函数
var Promise = function (executor) {
let self = this;
//没个promise都会有个初始化值,这个值在规范中叫做pending
self.status = 'pending';
self.value = undefined; // 默认成功的值
self.reason = undefined; // 默认失败的原因
self.onResolvedCallbacks = []; // 存放then成功的回调
self.onRejectedCallbacks = []; // 存放then失败的回调
// 成功状态要执行的函数
function resolve(value) {
//更改他的状态值,为成功,且不能更改
if (self.status === 'pending') {
self.status = 'resolved';
self.value = value;
//实例多次调用then(),循环释放数组
self.onResolvedCallbacks.forEach(function (fn) {
fn();
});
}
}
// 失败状态要执行的函数
function reject(reason) {
//更改他的状态值,为失败,且不能更改
if (self.status === 'pending') {
self.status = 'rejected';
self.reason = reason;
//实例多次调用then(),循环释放数组
self.onRejectedCallbacks.forEach(function (fn) {
fn();
})
}
}
如果直接传入错误的代码,那么直接进入reject
try {
executor(resolve, reject)
} catch (e) {
// 捕获的时候发生异常,就直接失败了
reject(e);
}
}

下面我们来实现then()方法,个方法每个实例都有,他是一个方法,所以我们把它挂载到Promise原型上:

Promise.prototype.then = function (onFulfilled, onRjected) {
//成功和失败默认一个函数,防止报错,
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
return value;
}
onRjected = typeof onRjected === 'function' ? onRjected : function (err) {
throw err;
}
let self = this;
//定义一个返回的promise
let promise2;
//当状态是成功的时候,可能会在函数中再次返回一个promise
if (self.status === 'resolved') {
promise2 = new Promise(function (resolve, reject) {
// 当成功或者失败执行时有异常那么返回的promise应该处于失败状态
//这个x 是第一个promise执行后的结果
// x可能是一个promise 也有可能是一个普通的值
setTimeout(function () {
try {
let x = onFulfilled(self.value);
// x可能是别人promise,写一个方法统一处理
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
}
//当状态是失败的时候
if (self.status === 'rejected') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onRjected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}) })
}
// 当调用then时可能没成功 也没失败
if (self.status === 'pending') {
promise2 = new Promise(function (resolve, reject) {
// 此时没有resolve 也没有reject
self.onResolvedCallbacks.push(function () {
setTimeout(function () {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
});
self.onRejectedCallbacks.push(function () {
setTimeout(function () {
try {
let x = onRjected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
});
})
}
return promise2;
}

集中处理x

function resolvePromise(promise2, x, resolve, reject) {
// 有可能这里返回的x是别人的promise
// 先跑错
if (promise2 === x) { //这里应该报一个类型错误,有问题
return reject(new TypeError('循环引用了'))
}
// 看x是不是一个promise,promise应该是一个对象
let called; // 表示是否调用过成功或者失败
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
//根据语法规定的几种情况来判断
// 可能是promise {},看这个对象中是否有then方法,如果有then我就认为他是promise了
try {
let then = x.then;
if (typeof then === 'function') {
// 成功
then.call(x, function (y) {
if (called) return
called = true
// y可能还是一个promise,在去解析直到返回的是一个普通值
//递归调用这个函数,
resolvePromise(promise2, y, resolve, reject)
}, function (err) { //失败
if (called) return
called = true
reject(err);
})
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true;
reject(e);
}
} else { // 说明是一个普通值1
resolve(x); // 表示成功了
}
}

在实现了这些之后,其他的方法,更多的就是一个语法糖,我们来实现他们

catch:

	catch实际上就是reject,所以一般建议在then里面不穿reject(),而链式调用catch方法
Promise.prototype.catch = function (callback) {
return this.then(null, callback)
}

all

//会传入一个数组,这个数组是promise集合
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
//arr是最终返回值的结果
let arr = [];
// 表示成功了多少次
let i = 0;
function processData(index, y) {
arr[index] = y;
if (++i === promises.length) {
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (y) {
processData(i, y)
}, reject)
}
})
}

race

//race就是赛跑的意思,谁获取结果比较快,就返回谁
// 只要有一个promise成功了 就算成功。如果第一个失败了就失败了
Promise.race = function (promises) {
return new Promise(function (resolve, reject) {
for (var i = 0; i < promises.length; i++) {
promises[i].then(resolve,reject)
}
})
}
// 生成一个成功的promise
Promise.resolve = function(value){
return new Promise(function(resolve,reject){
resolve(value);
})
}
// 生成一个失败的promise
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
})
}

defer 延期处理

会包容promise 可用于封装在传递方法之外调用原有的promise回调

Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise(function (resolve, reject) {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd
}

Promise 解析的更多相关文章

  1. Promise解析(待完成)

    Promise是一种异步操作的解决方案,将写法复杂的传统的回调函数和监听事件的异步操作,用同步代码的形式表达出来.避免了多级异步操作的回调函数嵌套. 1.主要用于异步计算 2.可以将异步操作队列化,按 ...

  2. Promise,Generator(生成器),async(异步)函数

    Promise 是什么 Promise是异步编程的一种解决方案.Promise对象表示了异步操作的最终状态(完成或失败)和返回的结果. 其实我们在jQuery的ajax中已经见识了部分Promise的 ...

  3. Netty源码解析—客户端启动

    Netty源码解析-客户端启动 Bootstrap示例 public final class EchoClient { static final boolean SSL = System.getPro ...

  4. 基于PromiseA+规范实现一个promise

    实现如果下规范的promise Aplus规范 1,promise是一个类:有三个状态 pending/等待态 fulfilled/成功态 rejected/失败态 2,promise默认执行器立即执 ...

  5. AngularJS之代码风格36条建议【一】(九)

    前言 其实在新学一门知识时,我们应该注意下怎么书写代码更加规范,从开始就注意养成一个良好的习惯无论是对于bug的查找还是走人后别人熟悉代码都是非常好的,利人利己的事情何乐而不为呢,关于AngularJ ...

  6. 使用 Promises 编写更优雅的 JavaScript 代码

    你可能已经无意中听说过 Promises,很多人都在讨论它,使用它,但你不知道为什么它们如此特别.难道你不能使用回调么?有什么了特别的?在本文中,我们一起来看看 Promises 是什么以及如何使用它 ...

  7. ES6核心内容精讲--快速实践ES6(三)

    Promise 是什么 Promise是异步编程的一种解决方案.Promise对象表示了异步操作的最终状态(完成或失败)和返回的结果. 其实我们在jQuery的ajax中已经见识了部分Promise的 ...

  8. Netty源码分析(三):客户端启动

    Bootstrap Bootstrap主要包含两个部分,一个是服务器地址的解析器组AddressResolverGroup,另一个是用来工作的EventLoopGroup. EventLoopGrou ...

  9. js async await 终极异步解决方案

    既然有了promise 为什么还要有async await ? 当然是promise 也不是完美的异步解决方案,而 async await 的写法看起来更加简单且容易理解. 回顾 Promise Pr ...

随机推荐

  1. 国外的非常好的开发提问回答的网站https://stackoverflow.com/questions

    https://stackoverflow.com/questions 可以进行搜索,在页面顶部,有搜索输入框

  2. 彻底弄懂angularJS表单验证

    常用的表单验证指令 (基本概念) 1. 必填项验证 某个表单输入是否已填写,只要在输入字段元素上添加HTML5标记required即可: <input type="text" ...

  3. Python long() 函数

    描述 long() 函数将数字或字符串转换为一个长整型.高佣联盟 www.cgewang.com 语法 long() 函数语法: class long(x, base=10) 参数 x -- 字符串或 ...

  4. Python File close() 方法

    概述 close() 方法用于关闭一个已打开的文件.高佣联盟 www.cgewang.com 关闭后的文件不能再进行读写操作, 否则会触发 ValueError 错误. close() 方法允许调用多 ...

  5. PHP strnatcmp() 函数

    实例 使用"自然"算法来比较两个字符串(区分大小写): <?php高佣联盟 www.cgewang.comecho strnatcmp("2Hello world! ...

  6. luogu P4887 模板 莫队二次离线 莫队 离线

    LINK:模板莫队二次离线 很早以前学的知识点 不过 很久了忘了. 考虑暴力 :每次莫队更新的时候 尝试更新一个点到一个区间的答案 可以枚举二进制下位数为k的数字 看一下区间内的这种数字有多少个. 不 ...

  7. 5.13 省选模拟赛 优雅的绽放吧,墨染樱花 多项式 prufer序列 计数 dp

    LINK:优雅的绽放吧,墨染樱花 当时考完只会50分的做法 最近做了某道题受到启发 故会做这道题目了.(末尾附30分 50分 100分code 看到度数容易想到prufer序列 考虑dp统计方案数. ...

  8. intel:spectre&Meltdown侧信道攻击(一)

    只要平时对安全领域感兴趣的读者肯定都听过spectre&Meltdown侧信道攻击,今天简单介绍一下这种攻击的原理( https://www.bilibili.com/video/av1814 ...

  9. linux的文件处理(匹配 正则表达式 egrep awk sed)和系统、核心数据备份

    文件处理 1.处理方式 匹配 正则表达式 egrep awk sed 2.文件中的处理字符 \n  新行符 换行 \t  制表符 tab键 缺省8个空格 \b  退格符 backspace键 退格键 ...

  10. Workerman学习笔记(一)初步认识

    本文只是概念性的知识,内容比较零散,下篇文章再进行代码分析. Workerman是什么,他的优势在哪? 官方给的解释是高性能socket框架,我的个人理解是实现多进程的通讯的服务框架. 与传统的PHP ...