promise内部实现原理,promise三种状态和执行原理
前端的Promise是干啥的?
Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件。ES6统一了用法,并原生提供了Promise对象。作为对象,Promise有以下两个特点:
(1)对象的状态不受外界影响。
(2)一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态。
可以通过Promise的构造函数创建Promise对象。
var?promise?=?new?Promise(function(resolve,reject)setTimeout(function(){??????????????????????????????
??console.log("hello?world");},2000);
});
Promise构造函数接收一个函数作为参数,该函数的两个参数是resolve,reject,它们由JavaScript引擎提供。其中resolve函数的作用是当Promise对象转移到成功,调用resolve并将操作结果作为其参数传递出去;reject函数的作用是单Promise对象的状态变为失败时,将操作报出的错误作为其参数传递出去。如下面的代码:
???function?greet(){????var?promise?=?new?Promise(function(resolve,reject){????????var?greet?=?"hello??world";
????????resolve(greet);
????});????return?promise;
????}
????greet().then(v={????console.log(v);//*
????})
上面的*行的输出结果就是greet的值,也就是resolve()传递出来的参数。
注意:创建一个Promise对象会立即执行里面的代码,所以为了更好的控制代码的运行时刻,可以将其包含在一个函数中,并将这个Promise作为函数的返回值。
Promise的then方法
??promise的then方法带有以下三个参数:成功回调,失败回调,前进回调,一般情况下只需要实现第一个,后面是可选的。Promise中最为重要的是状态,通过then的状态传递可以实现回调函数链式操作的实现。先执行以下代码:
function?greet(){var?promise?=?new?Promise(function(resolve,reject){????var?greet?=?"hello??world";
????resolve(greet);
});return?promise;
}var?p?=?greet().then(v={console.log(v);
})console.log(p);
Promise简书
promise是什么?
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列
为什么会有promise?
为了避免界面冻结(任务)
同步:假设你去了一家饭店,找个位置,叫来服务员,这个时候服务员对你说,对不起我是“同步”服务员,我要服务完这张桌子才能招呼你。那桌客人明明已经吃上了,你只是想要个菜单,这么小的动作,服务员却要你等到别人的一个大动作完成之后,才能再来招呼你,这个便是同步的问题:也就是“顺序交付的工作1234,必须按照1234的顺序完成”。
异步:则是将耗时很长的A交付的工作交给系统之后,就去继续做B交付的工作,。等到系统完成了前面的工作之后,再通过回调或者事件,继续做A剩下的工作。
AB工作的完成顺序,和交付他们的时间顺序无关,所以叫“异步”。
resolve作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;
promise状态一经改变,不会再变。
Promise对象的状态改变,只有两种可能:
从pending变为fulfilled
从pending变为rejected。
这两种情况只要发生,状态就凝固了,不会再变了
1.Promise.all() 批量执行
Promise.all([p1, p2, p3])用于将多个promise实例,包装成一个新的Promise实例,返回的实例就是普通的promise
它接收一个数组作为参数
数组里可以是Promise对象,也可以是别的值,只有Promise会等待状态改变
当所有的子Promise都完成,该Promise完成,返回值是全部值得数组
有任何一个失败,该Promise失败,返回值是第一个失败的子Promise结果
常见用法:
异步操作和定时器放在一起,,如果定时器先触发,就认为超时,告知用户;
例如我们要从远程的服务家在资源如果5000ms还没有加载过来我们就告知用户加载失败
2.Promise.race()
与 Promise.all 类似,但只等待第一个 settled 的 promise 并获取其结果(或 error)。
3.Promise.allSettled()
等待所有的 promise 都被 settle,无论结果如何。结果数组具有:
4.Promise.resolve()
Promise.resolve(value) 用结果 value 创建一个 resolved 的 promise。
5.Promise.reject()
Promise.reject(value) 用结果 value 创建一个 rejected 的 promise。
现实中的用法
回调包装成Promise,他有两个显而易见的好处:
1、可读性好
2、返回 的结果可以加入任何Promise队列
原文地址:
可参考:
promise的三种状态
promise的三种状态
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署Promise更好的选择。
如何用Promise控制for循环的异步流程
一.定义
promise是对异步编程的一种抽象。它是一个代理对象,代表一个必须进行异步处理的函数返回的值或抛出的异常。也就是说promise对象代表了一个异步操作,可以将异步对象和回调函数脱离开来,通过then方法在这个异步操作上面绑定回调函数。
遵循的是commonJS promise/A+规范。
1.状态
promise有3种状态:pending(待解决,这也是初始化状态),fulfilled(完成),rejected(拒绝)。
2.接口
promise唯一接口then方法,它需要2个参数,分别是resolveHandler和rejectedHandler。并且返回一个promise对象来支持链式调用。
promise的构造函数接受一个函数参数,参数形式是固定的异步任务,举一个栗子:
function sendXHR(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.open('get', 'QueryUser', true);
xhr.onload = function(){
if((xhr.status = 200 xhr.status 300) || xhr.status === 304){
resolve(xhr.responseText);
}else{
reject(new Error(xhr.statusText));
}
};
xhr.onerror = function(){
reject(new Error(xhr.statusText));
}
xhr.send(null)
}
二.实现
要实现promise对象,首先要考虑几个问题:
1.promise构造函数中要实现异步对象状态和回调函数的剥离,并且分离之后能够还能使回调函数正常执行
2.如何实现链式调用并且管理状态
首先是构造函数:
//全局宏定义
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
//Promise构造函数
function Promise(fn){
var self = this;
self.state = PENDING;//初始化状态
self.value = null;//存储异步结果的对象变量
self.handlers = [];//存储回调函数,这里没保存失败回调函数,因为这是一个dome
//异步任务成功后处理,这不是回调函数
function fulfill(result){
if(self.state === PENDING){
self.state = FULFILLED;
self.value = result;
for(var i=0;iself.handlers.length;i++){
self.handlers[i](result);
}
}
}
//异步任务失败后的处理,
function reject(err){
if(self.state === PENDING){
self.state = REJECTED;
self.value = err;
}
}
fnfn(fulfill,reject);
};
构造函数接受一个异步函数,并且执行这个异步函数,修改promise对象的状态和结果。
回调函数方法then:
//使用then方法添加回调函数,把这次回调函数return的结果当做return的promise的resolve的参数
Promise.prototype.then = function(onResolved, onRejected){
var self = this;
return new Promise(function(resolve, reject){
var onResolvedFade = function(val){
var ret = onResolved?onResolved(val):val;//这一步主要是then方法中传入的成功回调函数通过return来进行链式传递结果参数
if(Promise.isPromise(ret)){//回调函数返回值也是promise的时候
ret.then(function(val){
resolve(val);
});
}
else{
resolve(ret);
}
};
var onRejectedFade = function(val){
var ret = onRejected?onRejected(val):val;
reject(ret);
};
self.handlers.push(onResolvedFade);
if(self._status === FULFILLED){
onResolvedFade(self._value);
}
if(self._status === REJECTED){
onRejectedFade(self._value);
}
});
}
测试代码:
function async(value){
var pms = new Promise(function(resolve, reject){
setTimeout(function(){
resolve(value);;
}, 1000);
});
return pms;
}
async(1).then(function(result){
console.log('the result is ',result);//the result is 2
return result;
}).then(function(result){
console.log(++result);//2
});