这篇文章需要技术复核。如何帮忙。
这篇文章需要文法复核。如何帮忙。
Promise对象代表暂时不可用的值。
一个已存在的promise引用可以通过不同的方式被接收,如作为异步API的返回值。一旦得到一个promise对象,就可以调用其 then()
方法,以在其值可用时或者出现异常时执行一个动作。
可以通过 new Promise()
方法创建Promise对象,当使用一个已存在的Promise对象时,不需要引入 Promise.jsm
模块。
promise内部状态可为以下三种之一:
- 未完成状态(pending),此时完成值还不可用,它是唯一一个能够转换为其他状态的状态。
- 已完成状态(fulfilled),此时完成值可用,完成值与promise永久绑定,可为任意值,包括
undefined。
- 拒绝状态(rejected),出现错误时,拒绝理由与promise永久绑定,可为任意值,包括
undefined
,一般情况下为Error
对象。
备注: 使用promise时,应该始终对异常(拒绝理由)进行处理或报告。如果你看见了"A promise chain failed to handle a rejection"的错误信息,你可能就需要检查你的代码。参见下面的 异常处理和常见误区。
文档约定
文档规定,完成值的类型通过尖括号内的内容指定。如 OS.File.exists
方法返回一个完成值类型为boolean
的promise:
Promise<boolean> exists(string path);
拒绝理由可能在function文档中单独规定,除非特别指定,一般使用 Error
对象作为拒绝理由。
方法概览
Promise then([optional] Function onFulfill, [optional] Function onReject ); |
Promise catch([optional] Function onReject); |
构造函数
创建一个新的promise,初始化为等待状态,并提供解决函数的引用,用于改变其状态。
new Promise(executor);
参数
executor
-
该函数会马上被调用,它带有两个参数的函数对象:
-
executor(resolve, reject);
构造函数直到执行完成才会返回。解决函数可以在任何时间被调用,在执行过程完成前后都可以,其目标是控制promise的最终状态。如果执行过程抛出异常,异常值会被传递到reject解决函数中。
解决函数
resolve()
用特定值满足绑定的promise,或者把状态传递到一个已存在的promise。如果绑定的promise已经被解决(可能是一个值,也可能是一个rejection,或者是另一个promise),该方法不会做任何事。
备注: 调用该方法时,如果用一个pending状态的promise作为aValue参数,然后在该promise状态改变为fullfilled或者rejected前用另一个值再次调用,第二次调用将不会生效,因为这个绑定的promise已经被pending promise所解决了。
void resolve(
aValue
);
参数
aValue
可选- 如果这个值不是一个promise,包括
undefined
, 它会变成绑定promise的实现值。如果这个值是promise,绑定promise会被传递的promise解决,并跟随所提供的promise的状态(包括任何未来的转变)。
reject()
用特定原因拒绝绑定的promise。如果promise已经被解决了,不管是值,拒绝,还是另一个promise,这个方法都不会做任何事。
void reject(
aReason
);
参数
aReason
可选- 绑定promise的拒绝原因。通常是一个 Error 对象,就像在异常处理那样,尽管理由也可以是
undefined。
备注: 该参数不应该是promise。要说明一个被拒绝的promise,应该让拒绝原因等于被拒绝promise自身,而非其拒绝原因。
方法
then()
一旦promise完成或被拒绝,就立即执行一个回调函数,并返回一个新的promise对象,新promise的状态取决于promise和传入的回调函数
then
返回值后被调用,即使promise早已完成或已被拒绝。也可对多次调用同一个promise的then
方法。所有的回调函数会按照其注册的顺序被调用。
警告: 如果 onFulfill
抛出异常,不会调用 onReject
,异常也不会被捕获和输出到控制台(你会看到一个promise chain失败错误),可以在返回的promise上注册一个错误处理函数,以处理在任一回调中出现的异常(使用 catch() 或者 then() ),来处理发生在任何一个注册回调函数的异常。
注意:当多次调用同一个promise的then方法,所有注册的回调函数独立执行。如,当在一个回调函数中出现异常时,不会影响后面回调函数的执行。回调函数的结果只会对其注册所使用的then方法返回的promise产生影响,每一次调用then方法返回的都是不同的promise对象。
Promise then( Function onFulfill, Function onReject );
参数
onFulfill
可选- 当promise完成时,会调用该函数,并将完成值作为其唯一参数传入,该函数的输出会决定新的promise的状态。如果该参数不是函数(通常为
null
),则由then返回的新的promise的状态为已完成,且完成值与原promise相同 onReject
可选-
当promise被拒绝时,会调用该函数,并将拒绝理由作为其唯一参数传入,且该函数的输出会决定新的promise的状态。如果该参数不是函数(通常为
undefined
),则由then
返回的新的promise的状态为拒绝,且拒绝理由与原promise相同。
返回值
新的promise对象,初始状态为未完成,最终状态取决于回调函数的输出:
-
如果返回的不是promise,包括
undefined
,则新promise的状态为已完成,并将该返回值作为其完成值,即使原promises被拒绝 -
如果抛出异常,则新的promise的状态为拒绝,并将该异常作为其拒绝理由,即使原promise已完成
-
如果返回promise,则新promise的最终状态与回调函数返回的promise状态相同。
catch()
等价于调用onFulfill参数为undefined的
then()
方法。如果你链式调用then( onFulfill ).catch( onReject ),onFulfill中抛出的异常会被捕捉并传递到onReject。
Promise catch(
Function onReject
);
等价于以下调用:
p.then(undefined, logError);
p.catch(logError);
调试
按照设计,在不调用 then()
的情况下,promise的即时状态和值不能通过代码同步检测到。
为了有助于调试,只有当手动检查promise时,才能看到那些不能通过代码访问的特殊属性的信息(目前由于缺少复杂的语言或调试器的支持,属性名是随机生成的)。
这些代码可访问和可审查的属性有:
{{private:status}}
: 0代表未完成,1代表已完成,2代表拒绝。{{private:value}}
:完成值或拒绝理由,仅在promise已完成或已拒绝时有值。{{private:handlers}}
: 对象数组,这些对象保存了对回调函数的引用,仅在未完成状态下可用。
示例
请看 示例 页面.
异常处理和常见误区
promise应该报告未处理的错误,除非交给其他程序处理该错误。
// ###### WRONG: Silently drops any rejection notified by "OS.File.Exists". OS.File.exists(path).then(exists => { if (exists) myRead(path); }); // ###### WRONG: Silently drops any exception raised by "myRead". OS.File.exists(path).then(exists => { if (exists) myRead(path); }, Components.utils.reportError); // CORRECT (for example, might report the exception "myRead is not defined") OS.File.exists(path).then(exists => { if (exists) myRead(path); }) .then(null, Components.utils.reportError); // CORRECT (the function returns a promise, and the caller will handle the rejection) function myReadIfExists(path) { return OS.File.exists(path).then(exists => { if (exists) myRead(path); }); }
参见
- Promise.jsm
- Deferred
- JavaScript OS.File
- Promises, Promises: a useful simple explanation by Stuart Langridge
- WHATWG Living Standard