【问题标题】:When or who does pass resolve and reject functions to JS promises?何时或谁将解析和拒绝功能传递给 JS 承诺?
【发布时间】:2017-02-24 02:12:39
【问题描述】:

我已经开始学习 javascript promises。但我就是无法理解承诺的概念。 最困扰我的是谁将 Resolver 和 Reject 函数传递给 promise 构造函数?

查看这个 Promise 示例:

function getImage(url){
    return new Promise(function(resolve, reject){
        var img = new Image()
        img.onload = function(){
            resolve(url)
        }
        img.onerror = function(){
            reject(url)
        }
        img.src = url
    })
}

现在谁会通过 resolve 和 reject 方法,因为我对 javascript 的理解告诉我这个脚本会抛出未知变量错误,因为 resolve 和 rejects 没有定义?

getImage('doggy.jpg').then(function(successurl){
    document.getElementById('doggyplayground').innerHTML = '<img src="' + successurl + '" />'
}).catch(function(errorurl){
    console.log('Error loading ' + errorurl)
})

现在你看到了像上面这样的方法,传递这些方法(resolve 和 reject)的唯一方法是通过 then 和 catch,就像上面对 getImage 的方法调用中使用的那样。

【问题讨论】:

  • resolvereject 是您传递给Promise 的函数的参数。 Promise 本身调用这个函数并传入两个参数。
  • 比较:function cb(resolve, reject) { ... }; new Promise(cb);——这有帮助吗……?
  • @deceze 它确实帮助了我,但是我仍然对一件事感到困惑,那么为什么使用“then”和“catch”来传递其他方法?它们的工作方式就好像传入的方法是解析和拒绝方法一样?
  • 是的,而不是调用resolve,然后调用你的then回调,你可以直接调用你的then回调。本质上是一样的。 然而,promise 使您能够组合(链接)此类回调,如果您直接调用回调,这些方法很快就会变得非常复杂。 特别是如果您考虑到错误处理的复杂性,它承诺使用可链接的catch 回调很容易解决。

标签: javascript promise


【解决方案1】:

最困扰我的是谁将 Resolver 和 Reject 函数传递给 promise 构造函数?

没有人。

函数由 promise 构造函数传递。

它们被传递给 您作为第一个参数传递给 Promise 构造函数的函数。

【讨论】:

  • 那么我们为什么要传递变量来解析和拒绝方法:resolve(url) 这个变量可以是任何东西,从外部范围传递变量是没有意义的,因为该方法是系统生成的,可以是任何东西。跨度>
  • 解析器和拒绝器函数将变量传递给then 函数,但这些变量不是由 Promise API 生成的。
【解决方案2】:

Promise 构造函数使用回调进行初始化,构造函数在调用回调时将rejectresolve 作为参数传递。

这是一个简单的演示:

class PromiseDemo {
  constructor(cb) {
    cb(this.resolve.bind(this), this.reject.bind(this));
  }
  
  resolve(d) {
    console.log('resolve', d);
  }
  
  reject(d) {
    console.log('reject', d);
  }
}

new PromiseDemo((resolve, reject) => {
  Math.random() > 0.5 ? resolve('1') : reject('1');
});

【讨论】:

  • 那么,resolvereject 是参数的唯一原因是将this 绑定到Promise 对象?为什么需要这种绑定?
  • resolve 和 reject 作为回调传递,它们失去了对this 的引用。如果你想在 resolve/reject 中使用this,你需要绑定它们。在示例中,this 没有在其中任何一个中使用,因此您可以跳过绑定。
  • 我的问题确实如下。既然resolvereject 是内置函数,为什么要让回调函数接受它们作为参数呢?回调函数可以像任何其他内置函数一样简单地调用它们......
【解决方案3】:

我在理解 Promises 时遇到了同样的问题。你需要仔细查看 Promise 的创建过程。 当你写 var promise= new Promise(function(resolve,reject){...})

您实际上是在调用 Promise 类的构造函数或创建 Promise 类的对象。现在 Promise 构造函数需要一个函数回调。 现在 resolve 和 reject 只是函数参数,而不是任何其他值。 你可以写任何东西来代替resolve或reject,比如resolveHandler或rejectHandler。

这些resolve或reject只不过是Promise在Promise执行时调用的函数回调。

现在当 Promise 执行成功时调用 resolve,当 promise 执行出错或不成功时调用 reject。

调用resolve的参数可以像这样在then内部访问

getImage().then(function(valueSentInResolve){ console.log('')})

调用reject的参数可以像这样在catch内部访问

getImage().then(function(valueSentInResolve)
  {//..do something}
).catch(function(errorSentInReject){
  console.log('error',errorSentInReject )
})

希望对您有所帮助。如果我说错了,请告诉我。

【讨论】:

    【解决方案4】:

    promise 库创建并传递这些函数,以及跟踪 promise 和记录完成、存储状态和进度、取消它等所需的所有其他元数据。

    Bluebird 背后的人have published some info 了解图书馆内部的运作方式,您可以看到更多in the Bluebird source

    【讨论】:

      【解决方案5】:

      这有意义吗?这个解释可能完全不正确!!

      我们提供了应该异步运行的逻辑。该逻辑应接受 2 个函数,resolvereject。这些函数的引用由Promise 提供。当我们有最终值或错误时,我们的逻辑应该调用这些函数。最初创建的Promise 处于Pending 状态。调用resolvereject 将状态分别更改为FulfilledRejected

      executeFunction(res,rej) = {
       do some op, say DB query. 
       if (success) res(value) //executeFunction uses the resolving functions to change state of the Promise. Calling res fulfills the promise with value
       if (fail) rej(reason)//executeFunction uses the resolving functions to change state of the Promise. Calling rej rejects the promise with reason
      }
      

      我们不是直接调用executeFunction(这将使调用同步),而是创建一个Promise 将在一个单独的线程(异步)let p = Promise(executeFunction(res,rej)); 中运行executeFunction 代码。我们得到了 Promise 的引用。

      我的猜测是在Promise内部,会发生以下情况

      Promise(e(res,rej)) = { 
      
      // the Promise's constructor creates a new promise, initially in the pending state. It calls `e` (the executeFunction function) and provides references to the resolving functions to it that can be used to change its state.
        state = pending;
        e(_res,_rej); //starts my op. asynchronously (a new thread). Reference to resolving functions, _res, _rej is provided. _res and _rej are Promise's internal functions (see below)
        //constructor doesn't return till the async thread finishes
      }
      
      _res (value){ //Promise's internal method
       //probably sets the state of promise to Fulfilled and store the result of the Promise
       state = fulfilled
       resolvedValue = value;
      }
      
      _rej {//Promise's internal method
       probably sets the state of promise to Rejected and store the result of the Promise
       state = rejected
       resolvedValue = error;
      }
      

      创建Promise 开始异步执行代码。现在我们有兴趣知道executeFunction 的结果是什么(我们不在乎executeFunction 何时结束)。为此,我们调用 Promise p 中的 thenthen 接受两个可选参数并将它们注册为回调。我不确定何时以及由谁调用这些回调。我知道 then 返回另一个 Promise 但我无法理解它是如何工作的

         then(executeFnIfPromiseResolved, executeFnIfPromiseRejected):Promise {
            register executeFnIfPromiseResolved as callback 
            register executeFnIfPromiseRejected as callback
            //NOT SURE WHO AND WHEN THE CALLBACKS ARE CALLED
            //then needs to return Promise. What would be the executor function of that Promise?
      }
      

      【讨论】:

      • "Promise 将在单独的线程中(异步)运行 executeFunction 代码" - 不,这与多线程无关。事实上,它甚至不是异步的,new Promise 构造函数calls the executor callback synchronously。异步的事情是由那里的代码启动的,例如拨打setTimeout时。
      • 谢谢。您能否帮我理解then 的用途以及它是如何工作的,特别是回调的调用对象和方式?
      • 当 Promise 的状态发生变化时(或在已经解决的 Promise 上调用 then 时)安排回调。谁在呼唤他们?事件循环 - 这部分是本机异步的。
      【解决方案6】:

      我整天都在研究 Promise,并且有同样的问题。我终于想通了。

      当你创建一个 Promise 对象时,你给 Promise 构造函数一个executor,它可以是任何函数,只要它有这个签名。

      anyFunction(resolutionFunction, rejectionFunction){
          // typically, some asynchronous operation.
      }
      

      因此可以使用任何具有 2 个函数作为参数的函数。第一个函数是你在它工作时调用的函数,第二个是你在它中断时调用的函数。您也可以随意命名这些函数。

      Promise 构造函数接受你传入的函数并用它做一些事情。

      1. 它采用这 2 个函数参数并生成一对对应的函数,这些函数“连接”到 Promise 对象。
      2. 它运行执行器
      3. 它会忽略执行程序的任何返回值

      现在在你的 executor 函数中,当 promise 解决时,你调用 positionally first 函数并传递一个值。它看起来像:

      resolutionFunction(value)
      

      您可能想知道,resolutionFunction 是在哪里定义的? 请记住 Promise 构造函数为我们定义了该函数。所以我们可以调用resolutionFunction 而无需自己定义。在幕后,当我们调用由 Promise 构造函数生成的 resolutionFunction 时,它会将 Promise 的状态设置为已完成,调用 promiseObject.then 函数内部的函数,并将值传递给 .then 函数,以便您可以使用它。

      如果 Promise 失败,你会调用第二个位置函数,同样的事情会发生,你可以处理失败。

      这个Mozilla Doc on the Promise Constructor非常很有帮助。

      这里有一个简短的例子,展示了我上面解释的内容。

      function anyFunction(callThisFunctionWhenItWorks, callThisFunctionWhenItBreaks) {
        let importantNumber = 10; //change to 11 if you want the promise to reject
        if (importantNumber == 10) {
          callThisFunctionWhenItWorks('Hooray, success, so we call resolved for the promise.');
        } else {
          callThisFunctionWhenItBreaks('Boo, rejected because important number is not equal to 10');
        }
      }
      
      //make a new promise
      const examplePromise = new Promise(anyFunction);
      
      //use the promise
      examplePromise.then(function(result) {
        console.log(result);
      }).catch(function (error) {
        console.log(error);
      })
      

      【讨论】:

      • @deceze 您对原始问题的评论确实帮助我解决了这个问题。谢谢!
      猜你喜欢
      • 1970-01-01
      • 2013-06-22
      • 1970-01-01
      • 1970-01-01
      • 2013-04-28
      • 1970-01-01
      • 2023-01-16
      • 2021-11-02
      相关资源
      最近更新 更多