标准
https://promisesaplus.com/
An open standard for sound, interoperable JavaScript promises—by implementers, for implementers.
A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its
then
method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled.Terminology
- “promise” is an object or function with a
then
method whose behavior conforms to this specification.- “thenable” is an object or function that defines a
then
method.- “value” is any legal JavaScript value (including
undefined
, a thenable, or a promise).- “exception” is a value that is thrown using the
throw
statement.- “reason” is a value that indicates why a promise was rejected.
Requirements
Promise States
A promise must be in one of three states: pending, fulfilled, or rejected.
- When pending, a promise:
- may transition to either the fulfilled or rejected state.
- When fulfilled, a promise:
- must not transition to any other state.
- must have a value, which must not change.
- When rejected, a promise:
- must not transition to any other state.
- must have a reason, which must not change.
Here, “must not change” means immutable identity (i.e.
===
), but does not imply deep immutability.The
then
MethodA promise must provide a
then
method to access its current or eventual value or reason.A promise’s
then
method accepts two arguments:promise.then(onFulfilled, onRejected)
- Both
onFulfilled
andonRejected
are optional arguments:
- If
onFulfilled
is not a function, it must be ignored.- If
onRejected
is not a function, it must be ignored.- If
onFulfilled
is a function:
- it must be called after
promise
is fulfilled, withpromise
’s value as its first argument.- it must not be called before
promise
is fulfilled.- it must not be called more than once.
- If
onRejected
is a function,
- it must be called after
promise
is rejected, withpromise
’s reason as its first argument.- it must not be called before
promise
is rejected.- it must not be called more than once.
onFulfilled
oronRejected
must not be called until the execution context stack contains only platform code. [3.1].onFulfilled
andonRejected
must be called as functions (i.e. with nothis
value). [3.2]then
may be called multiple times on the same promise.
- If/when
promise
is fulfilled, all respectiveonFulfilled
callbacks must execute in the order of their originating calls tothen
.- If/when
promise
is rejected, all respectiveonRejected
callbacks must execute in the order of their originating calls tothen
.
then
must return a promise [3.3].promise2 = promise1.then(onFulfilled, onRejected);
- If either
onFulfilled
oronRejected
returns a valuex
, run the Promise Resolution Procedure[[Resolve]](promise2, x)
.- If either
onFulfilled
oronRejected
throws an exceptione
,promise2
must be rejected withe
as the reason.- If
onFulfilled
is not a function andpromise1
is fulfilled,promise2
must be fulfilled with the same value aspromise1
.- If
onRejected
is not a function andpromise1
is rejected,promise2
must be rejected with the same reason aspromise1
.The Promise Resolution Procedure
The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as
[[Resolve]](promise, x)
. Ifx
is a thenable, it attempts to makepromise
adopt the state ofx
, under the assumption thatx
behaves at least somewhat like a promise. Otherwise, it fulfillspromise
with the valuex
.This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant
then
method. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonablethen
methods.To run
[[Resolve]](promise, x)
, perform the following steps:
- If
promise
andx
refer to the same object, rejectpromise
with aTypeError
as the reason.- If
x
is a promise, adopt its state [3.4]:
- If
x
is pending,promise
must remain pending untilx
is fulfilled or rejected.- If/when
x
is fulfilled, fulfillpromise
with the same value.- If/when
x
is rejected, rejectpromise
with the same reason.- Otherwise, if
x
is an object or function,
- Let
then
bex.then
. [3.5]- If retrieving the property
x.then
results in a thrown exceptione
, rejectpromise
withe
as the reason.- If
then
is a function, call it withx
asthis
, first argumentresolvePromise
, and second argumentrejectPromise
, where:
- If/when
resolvePromise
is called with a valuey
, run[[Resolve]](promise, y)
.- If/when
rejectPromise
is called with a reasonr
, rejectpromise
withr
.- If both
resolvePromise
andrejectPromise
are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.- If calling
then
throws an exceptione
,
- If
resolvePromise
orrejectPromise
have been called, ignore it.- Otherwise, reject
promise
withe
as the reason.- If
then
is not a function, fulfillpromise
withx
.- If
x
is not an object or function, fulfillpromise
withx
.If a promise is resolved with a thenable that participates in a circular thenable chain, such that the recursive nature of
[[Resolve]](promise, thenable)
eventually causes[[Resolve]](promise, thenable)
to be called again, following the above algorithm will lead to infinite recursion. Implementations are encouraged, but not required, to detect such recursion and rejectpromise
with an informativeTypeError
as the reason. [3.6]
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise#Promise_%E5%8E%9F%E5%9E%8B
语法
new Promise( function(resolve, reject) {...} /* executor */ );
参数
- executor
- executor是带有
resolve
和reject
两个参数的函数 。Promise构造函数执行时立即调用executor
函数,resolve
和reject
两个函数作为参数传递给executor
(executor 函数在Promise构造函数返回新建对象前被调用)。resolve
和reject
函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦完成,可以调用resolve函数来将promise状态改成fulfilled,或者在发生错误时将它的状态改为rejected。- 如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。
例子
https://www.jianshu.com/p/459a856c476f
解决回调地狱的方法:
const request = url => { return new Promise((resolve, reject) => { $.get(url, data => { resolve(data) }); }) }; // 请求data1 request(url).then(data1 => { return request(data1.url); }).then(data2 => { return request(data2.url); }).then(data3 => { console.log(data3); }).catch(err => throw new Error(err));
http://www.cnblogs.com/lvdabao/p/es6-promise-1.html
function runAsync(){ var p = new Promise(function(resolve, reject){ //做一些异步操作 setTimeout(function(){ console.log('执行完成'); resolve('随便什么数据'); }, 2000); }); return p; } runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return '直接返回数据'; //这里直接返回数据 }) .then(function(data){ console.log(data); });
Q库
http://documentup.com/kriskowal/q/#
https://github.com/kriskowal/q
If a function cannot return a value or throw an exception without
blocking, it can return a promise instead. A promise is an object
that represents the return value or the thrown exception that the
function may eventually provide. A promise can also be used as a
proxy for a remote object to overcome latency.On the first pass, promises can mitigate the “Pyramid of
Doom”: the situation where code marches to the right faster
than it marches forward.step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) { step4(value3, function(value4) { // Do something with value4 }); }); }); });
With a promise library, you can flatten the pyramid.
Q.fcall(promisedStep1) .then(promisedStep2) .then(promisedStep3) .then(promisedStep4) .then(function (value4) { // Do something with value4 }) .catch(function (error) { // Handle any error from all above steps }) .done();
With this approach, you also get implicit error propagation, just like
try
,
catch
, andfinally
. An error inpromisedStep1
will flow all the way to
thecatch
function, where it’s caught and handled. (HerepromisedStepN
is
a version ofstepN
that returns a promise.)The callback approach is called an “inversion of control”.
A function that accepts a callback instead of a return value
is saying, “Don’t call me, I’ll call you.”. Promises
un-invert the inversion, cleanly separating the input
arguments from control flow arguments. This simplifies the
use and creation of API’s, particularly variadic,
rest and spread arguments.
BlueBird库
http://bluebirdjs.com/docs/getting-started.html
http://bluebirdjs.com/docs/features.html
http://bluebirdjs.com/docs/api-reference.html
API Reference
评价Promise
https://www.zhihu.com/question/25413141
如果着眼于现在和未来一段时间的话,建议用Promise,不论是ES6的还是用Q还是用bluebird,毫无疑问立即马上开始用。
如果眼光放长一点看的话,用了co以后基本上再也不愿回去了,即使是“正宫娘娘”Promise。
这co完全就是用yield/generator实现了async/await的效果啊,第一次见的时候,真是有种天马行空的感觉(原谅我见识少)。
它不仅能够“同步非阻塞”,也几乎没有剥夺我对多个非阻塞操作依赖关系或者竞争关系的精确控制,当我需要精确控制异步流程的时候,回去用Promise甚至callback,当我需要写的爽,一泻千里的时候,用async/await(扯远了)。