JavaScript之Promise实现
李牙刷儿 2017-12-18 20:42:48 浏览42 评论0 发表于: 阿里云ApsaraMobile(移动云)摘要: 自己动手写Promise
ES2015提出了Promise,同时基于Promise的异步开发将开发者中回调地狱中解救出来。但在没有原生支持的环境下,需要借助Promise/A+之类的库来实现Promise,今天就来尝试自行实现Promise。
1 基本实现
首先来完成一个Promise类的基本框架:
function Promise(fn) {
var resolveCallback = null
var rejectCallback = null
this.then = function(onResolved, onRejected) {
resolveCallback = onResolved
rejectCallback = onRejected
}
this.resolve = function(value) {
this.resolveCallback(value)
}
this.reject = function(reason) {
this.rejectCallback(reason)
}
fn(this.resolve, this.reject)
}
以上便是Promise的基本实现。
2 状态管理
上述的代码存在一个问题,resolve方法会调用多次,所以接下来我们需要接入状态管理。
Promise内部存在3个状态:
- pending
- resolved
- rejected
接下来在现有代码之上,加入状态管理:
function MyPromise(fn) {
let state = 'pending'
var resolveCallback = null
var rejectCallback = null
var childResolve
var childReject
this.then = function(onResolved, onRejected) {
resolveCallback = onResolved
rejectCallback = onRejected
}
this.resolve = function(value) {
if(state === 'pending') {
this.resolveCallback(value)
state = 'resolved'
}
}
this.reject = function(reason) {
if(state === 'pending') {
this.rejectCallback(reason)
state = 'rejected'
}
}
fn(this.resolve, this.reject)
}
3 链式调用
上述Promise实现可以完成正常的异步调用,但是却无法实现链式回调,原因在于其then方法没有返回一个新的Promise对象,所以接下来还需要改造then方法,实现链式调用:
this.then = function(onResolved, onRejected) {
if(state === 'pending') {
resolveCallback = onResolved
rejectCallback = onRejected
}
return new MyPromise((resolve, reject) => {
......
})
}
光返回一个promise对象还没用,接下来我们来写个demo测试下:
var demo = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('my first promise')
}, 1000)
})
demo.then((msg) => {
console.log(msg)
return 'my second promise'
}).then((msg) => {
console.log(msg)
})
其输出为:
my first promise
事实上,第二个promise对象的resolve reject方法从未被调用过,因而其onResolved onRejected的回调ye就无从调用。所以还必须指定时机调用字promise对象的resolve和reject。
所以首先需要在创建新promise对象时,记录其resolve和reject方法:
function MyPromise() {
......
var childResolve
var childReject
this.then = function(onResolved, onRejected) {
if(state === 'pending') {
resolveCallback = onResolved
rejectCallback = onRejected
}
return new MyPromise((resolve, reject) => {
childResolve = resolve
childReject = reject
})
}
}
接下来还需在resolve 和 reject方法中调用子对象的resolve和reject方法,整个Promise完整代码如下:
function MyPromise(fn) {
let state = 'pending'
var resolveCallback = null
var rejectCallback = null
var childResolve = null
var childReject = null
this.then = function(onResolved, onRejected) {
if(state === 'pending') {
resolveCallback = onResolved
rejectCallback = onRejected
}
return new MyPromise((resolve, reject) => {
childResolve = resolve
childReject = reject
})
}
this.resolve = function(value) {
if(state === 'pending') {
if(resolveCallback) {
var ret = resolveCallback(value)
childResolve(ret)
state = 'resolved'
}
}
}
this.reject = function(reason) {
if(state === 'pending') {
if(rejectCallback) {
var ret = rejectCallback(reason)
childReject(ret)
state = 'rejected'
}
}
}
fn(this.resolve, this.reject)
} 本文为云栖社区原创内容,未经允许不得转载,如需转载请发送邮件至yqeditor@list.alibaba-inc.com;如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。 用云栖社区APP,舒服~
【云栖快讯】中办国办印发《推进互联网协议第六版(IPv6)规模部署行动计划》加快推进基于 IPv6 的下一代互联网规模部署,计划指出2025年末中国 IPv6 规模要达到世界第一,阿里云也第一时间宣布了将全面提供IPv6服务,那么在全面部署 IPV6 前,你需要了解都在这儿 详情请点击 评论文章 (0) (0) (0)