首页 文章

JS Promises:Fulfill vs Resolve

提问于
浏览
9

我理解Promise存在于以下三种状态之一:Promise可以是 pending (未解析), fulfilled (已成功解析)或 rejected (已解决失败) .

通过阅读A+ Promise SpecMDN's documentation,我很困惑他们都承认 fulfilledrejected 状态,但在Promise构造函数的定义中,它们指定了两个回调: resolvereject . 我们似乎可以互换地使用这两个术语;他们不是 .

并不意味着成功:

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.

当我们实际承诺时,为什么我们在这里使用_2479860?是否有一个实例,我们传递给 resolve 的值可能会导致Promise被 reject 编辑?

3 回答

  • 2

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

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

    回答你的第一个问题是没有解决问题并且完成相同的事情:考虑我们传递给要解决的 Value 是未决承诺的情况 . 在这种情况下,我们自己的承诺将立即结果:

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

    在这种情况下,我们说承诺是“解决”另一个承诺,它仍然悬而未决 .

    这一切都发生在 then 的背后,因此可能更容易看一下 a 不支持promises(采取回调)的复古案例,而且我们没有正确地展平事物:

    // 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));
    

    在这里,我们更清楚地看到,决心被另一个承诺所呼唤 . 重要的是,已解决的承诺不会实现并触发 "after setTimeout" 消息,直到第二个承诺结算(来自 setTimeout 的非承诺 undefined 值),此时两个承诺都会得到满足(换句话说:这两个承诺刚刚形成resolve chain) .

    这是理解已解决的不同于履行或甚至解决(履行或拒绝,未待决)的关键 .

    来自States and Fates

    • 州:履行,拒绝,待决 .

    • 命运:已解决,尚未解决 .

    命运指的是单一承诺的命运是否已达到,并且由于解决链而不直接对应于任何状态转变 .

  • 4

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

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

    解决过程(解决承诺)可以在A+ spec中查看 .

    Edit .

    为什么人们通常使用 resolve 作为第一个参数名称's because the callback passed as the first argument invokes the resolution process. It doesn' t履行承诺(承诺仍然可以被拒绝),它只是开始解决承诺 . reject 机制未在规范中指定,它实际上是一种短路解决方案的过程,因此承诺用 reject 解决(实际上没有解决) .

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

    这是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);
    });
    
  • 2

    具有 Error 值的已解决 Promise 不会自动转换 Promise 拒绝 Promise

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

    另见States and fates


    如果您可以包含有关如何使用拒绝承诺而不是履行承诺的信息,我会认为这是一个完整的答案 .

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

    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 ,可以直接使用 unhandledrejection 事件, Promise.reject 或者铬/铬49可以使用 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)
    })
    

    也可以在 Promise 构造函数中使用 throw Error 而不使用 resolvereject ,这应该由 onRejectedcatch 处理

    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`  */
    })
    

    说明:根据应用程序和预期结果,有许多方法可以处理已解决和拒绝的对象.2479933_对象 .

相关问题