JS Promises:Fulfill vs Resolve

时间:2016-02-14 21:44:54

标签: javascript promise

我理解承诺存在于以下三种状态之一:承诺可以待定(未解决),履行(已成功解决)或被拒绝(解决失败)。

通过A+ Promise SpecMDN's documentation阅读,我很困惑他们都承认已履行被拒绝的状态但是在定义中承诺构造函数指定两个回调:解决拒绝。我们似乎可以互换地使用这两个术语;他们不是。

并不意味着成功:

re·solve /rəˈzälv/ verb
1. settle or find a solution to (a problem, dispute, or contentious matter).

意味着成功:

ful·fill /fo͝olˈfil/ verb
1. bring to completion or reality; achieve or realize (something desired, promised, or predicted).
2. carry out (a task, duty, or role) as required, pledged, or expected.

当我们实际履行承诺时,为什么我们在这里使用解决?是否有一个实例,我们传递给解决的值可能导致承诺拒绝编辑?

4 个答案:

答案 0 :(得分:4)

我们可以用另一个承诺来解决承诺。

首先回答你的第二个问题:是的,有一个实例,我们传递给它的值可能导致Promise被拒绝,那就是我们传递了一个拒绝的承诺,例如Promise.reject()

要回答第一个问题 解决履行:考虑我们传递给要解决的值是待定的情况承诺。在这种情况下,我们自己的承诺将立即 不能解决

a().then(() => new Promise(setTimeout)).catch(e => console.error(e));

在这种情况下,我们说承诺是"已经解决了#34;另一个承诺,它仍然悬而未决。

这一切都发生在我们then内部的背后,因此可能更容易看到a不支持承诺(回调)的复古案例,我们不会正确地平整事物:

// Old times and unflattened for exposition:
new Promise((resolve, reject) => a(function(result) {
  resolve(new Promise(setTimeout));
}, reject))
.then(() => console.log("after setTimeout"))
.catch(e => console.error(e));

在这里,我们更清楚地看到 resolve 被另一个承诺调用。重要的是,已解决的承诺不会履行并触发"after setTimeout"消息,直到第二个承诺结算(来自{的非承诺undefined值{1}}),此时两个承诺都变为履行(换句话说:这两个承诺刚刚形成resolve chain)。

这是理解已解决已履行或甚至已解决(已履行或已拒绝,未暂挂)不同的关键。

来自States and Fates

  • 声明:已履行已拒绝待决
  • fates:已解决未解决

命运指的是是否已达到单一承诺的命运,并且由于解析链而无法直接对应任何状态转换。

答案 1 :(得分:2)

价值为Promise的已解决Error不会自动将Promise转换为拒绝Promise

var p = Promise.resolve(new Error("rejected"));
p.then(function(data) {
  console.log(data, p)
})

另见States and fates

  

如果您可以包含有关如何使用解决方案的信息   拒绝承诺而不是实现它,我会考虑这个   完整答案。

不确定使用resolve拒绝Promise的原因或预期结果?虽然最简单的方法是在reject调用resolve时将Promise.resolve(Promise.reject(/* Error here */))作为参数传递

var _reject = function(err) {
  return Promise.reject(err)
}

var resolver = function(resolve, reject) {  
    return resolve(_reject(new Error("reject within resolve")))
}

var p = new Promise(resolver);

p.then(function(data) {
  console.log("resolved", data)
},function(data) {
  console.log("rejected:", data, "promise:", p)
})

如果预期结果是捕获错误或被拒绝的Promise传递给可能附加处理程序的resolve,则在保留"resolved" PromiseStatus的同时,可以使用{{1事件,unhandledrejection直接或铬/铬49+可以使用Promise.reject

PromiseRejectionEvent

还可以window.addEventListener("unhandledrejection", function(event) { // handle unhandled rejected `Promise` console.log("unhandledrejection:", event.reason, event.promise); }); Promise.resolve(new PromiseRejectionEvent("Error", { // unhandled `rejected` `Promise` promise: Promise.reject(new Error("custom rejection")), reason: "custom rejection" })) .then(function(data) { // `PromiseRejectionEvent` contains a `rejected` // `Promise` , which triggers `"unhandledrejection"` event // to handle rejected `Promise` here, resolve `.promise` // object of `PromiseRejectionEvent` console.log("resolved:", data); }, function(err) { console.log("rejected", err) }) throw Error Promise resolve reject onRejected catch new Promise(function(resolve, reject) { throw new Error("reject within Promise constructor") }) // catch here handles `Error` from `Promise` constructor // will be `resolved` at `.then()` if `Error` not `throw`n to `.then()` // .catch(function(e) { // console.log("caught error:", e); /* return e : pass `e` to `.then()` as `resolved` `Promise` */ /* throw e : pass `e` to `.then()` as `rejected` `Promise` */ //}) .then(function(data) { console.log("resolved:", data) }, function(err) { console.log("rejected:", err); throw err }) .catch(function(e) { console.log("caught error:", e); /* return e : pass `e` to `.then()` as `resolved` `Promise` */ /* throw e : pass `e` to `.then()` as `rejected` `Promise` */ }) {}} {}} 1}}

Promise

说明:根据应用程序和预期结果,有许多方法可以处理已解决和被拒绝的<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="5.3dp"/> <solid android:color="#000000"/> </shape> 对象。

答案 2 :(得分:2)

我认为承诺已经解决或解决了。承诺的解决方案是承诺从pending状态移动并获取与所述状态相关联的值的过程。因此,如果承诺是fulfilledrejected,那么它将是一个已解决的承诺(因为它的解决过程已经结束)。如果承诺进入解决过程并且从未转换到任何其他状态,则表示承诺未解决(解决过程从未结束)。

关于其他字词rejectedfulfilled,它们是pending承诺可以转换的其他两个状态。 reject是非常明显的IMO,它处理应该发生故障的情况。现在我同意fulfill可能有些含糊不清,因为它可能只是意味着承诺已成功完成(如在解决中)。它不应该描述解决过程,而是描述手头任务的成功(或没有错误)。

可以在A+ spec

中查看解决过程(解决承诺)

修改

人们通常使用resolve作为第一个参数的原因是因为作为第一个参数传递的回调调用了解析过程。它不履行承诺(承诺仍然可以被拒绝),它只是开始解决承诺。规范中没有指定reject机制,它实际上会使解析过程发生短路,因此承诺会以reject结算(实际上并未解决)。

以下是使用p拒绝resolve的一些示例:

这是2.3.1点。

var p = new Promise(resolve => setTimeout(() => resolve(p), 0));

这是2.3.2.3点。

var p = Promise.resolve(Promise.reject('reason'));

这是2.3.3.2点。

var thenable = { get then() { throw new Error(); } }
var p = Promise.resolve(thenable);

这是2.3.3.3.3

var thenable = {
    then: function(resolvePromise, rejectPromise){
        rejectPromise(new Error());
    }
}
var p = Promise.resolve(thenable);

这是2.3.3.4.2

var thenable = {
    then: function(){
        throw new Error();
    }
}
var p = Promise.resolve(thenable);

我在这里使用Promise.resolve而不是传递给Promise构造函数的函数的第一个参数,但它们应该是相同的。很多时候传递给构造函数的resolve函数是:

var p = this;
var cb = function(x){
    resolve(p, x);
}

您当然可以将这些测试写为:

var p = new Promise(function(resolve){
    resolve(thenable);
});

答案 3 :(得分:0)

实际上, resolve 回调并不意味着该诺言将被兑现。

已实现,已拒绝,未决,已解决,已解决已锁定 EcmaScript2015 specs, 25.4 Promise Objects

  

任何Promise对象都处于以下三种互斥状态之一:已实现已被拒绝待处理

     
      
  • 如果p立即将Job放入队列以调用函数p.then(f, r),则兑现承诺f

  •   
  • 如果p立即将Job放入队列以调用函数p.then(f, r),则承诺r被拒绝。

  •   
  • 一个诺言既未兑现也不被拒绝。

  •   
     

如果未兑现承诺,即已兑现或拒绝,则称为已兑现。

     

一个承诺已解决或已被“锁定”以匹配另一个承诺的状态,则该承诺已被解决。   尝试解决或拒绝已解决的承诺没有任何效果。如果未兑现承诺,则为未解决。   未解决的承诺始终处于待处理状态。已解决的承诺可能尚未完成,已实现或被拒绝。

简短的概述,在这里我将使用术语“自主”与“锁定”相反。它们是诺言的依赖情况的两个可能值:

+---------------------+------------+-----------+-----------+----------+
| action              | dependency | state     | resolved? | settled? |
+---------------------+------------+-----------+-----------+----------+
| new Promise()       | autonomous | pending   |    no     |    no    |
| - resolve(thenable) | locked-in  | pending*  |    yes    |    no    |
| - resolve(other)    | autonomous | fulfilled |    yes    |    yes   |
| - reject(any)       | autonomous | rejected  |    yes    |    yes   |
+---------------------+------------+-----------+-----------+----------+

* thenable现在可以控制我们的promise对象的未来状态。

以上引述中提到,一个承诺已被锁定以匹配“另一个承诺”的状态 ,但是更准确地说,“其他承诺”也可以是一个非承诺的“ thenable”,例如可以在流程说明的步骤11和12中看到 在25.4.1.3.2

  
      
  1. 如果IsCallable( thenAction )是false,则
      一种。返回FulfillPromise( promise,resolution )。
  2.   
  3. 执行EnqueueJob("PromiseJobs",PromiseResolveThenableJob,«Promise,Resolution,thenAction»
  4.   

resolve的演示被thenable调用,从而触发拒绝:

const thenable = { // Could be a promise object, but does not have to be
    then(success, fail) {
        setTimeout(() => fail("gotcha!"), 1000);
    }
}

const p = new Promise((resolve, reject) => {
    console.log("1. The promise is created as pending");
    setTimeout(() => {
        resolve(thenable);
        console.log("2. It's resolved with a thenable; it's not yet settled");
    }, 1000);
});

p.catch(err => 
   console.log(`3. It's settled as rejected with error message "${err}"`)
);