【问题标题】:Struggling with promises - how to do something in inner then before outer then gets called?与承诺作斗争 - 如何在内部然后在外部然后被调用之前做一些事情?
【发布时间】:2019-10-12 08:56:46
【问题描述】:

不知道如何问这个问题,而且我真的在为 promises 苦苦挣扎,所以我将尝试一个简化的示例。

假设我有一个接受回调的函数。在那个函数中,我想进行一个也有回调的异步调用,所以当它的回调被调用时,我会根据它的响应做一些事情,然后调用我的回调。

someFunction = function(callback) {
    var startTime = (+new Date());
    someAsyncCall(function() {
        var endTime = (+new Date());
        callback(startTime, endTime);
    });
};

函数的作用无关紧要,因为我对事物的结构和顺序感兴趣。但是这个例子只是记录了内部异步调用前后的时间,然后调用回调报告该信息。

现在,对于我的问题,假设 someAsyncCall 已转换为 Promise,并且 someFunction 也已转换为返回该 Promise 并且不接受回调。所以,在结构上,我的函数现在看起来像这样:

someFunction = function() {
    var startTime = (+new Date());
    return someAsyncCall();
    // How to capture endTime on then before moving on?
};

问题是,我现在想在 someAsyncCall() 之后捕获结束时间,并将这些数据记录在某处,大概是在 someAsyncCall() 的 then 条件下,在 someFunction() 的 then 条件被调用之前。我该怎么做?


更新: 我似乎没有得到我正在寻找的答案(或者它只是没有通过我的厚脑袋),所以也许以这种方式陈述我的问题的更好方法:

让我们从这段示例代码开始:

startProcess = function() {
    // Do a bunch of stuff here...
    return doProcess(someParams);
}

最终,doProcess 返回一个promise,该promise 由startProcess 返回。然后调用者对它做任何事情。

现在,我想在 doProcess 周围包装一些代码来捕获开始和结束时间,而不会对现有代码的操作造成任何干扰。有没有什么方法可以响应 doProcess 的完成以在它解决承诺之前做某事,通常,对于调用 startProcess 的任何东西?关键是,这个函数不知道是谁在调用它,也不知道调用者对 Promise 做了什么;它本质上只是 doProcess 的包装器。

【问题讨论】:

  • 代码中没有任何承诺...您会期望.then(根据问题标题的内部和外部)-或async/await-您的代码没有任何异步查看
  • So, structurally, my function would now look something like this: - 不,它不会...... How to capture endTime on then before moving on? - 因为你return someAsyncCall() 没有“继续前进”
  • someAsyncCall 里面有什么?我假设在某些时候它有promise.resolve(),在这种情况下,它似乎就像在解析调用之前添加callback() 一样简单......
  • 重点是,someAsyncCall 之前是一个异步操作,它调用提供给它的回调函数(在示例中作为立即函数),而 someFunction 提供了一个回调,我将在此之后调用它。但是现在 someAsyncCall 返回了一个 promise,它也由 someFunction 返回,所以调用者现在有了一个带有 then 条件的 promise。不确定它与 someAsyncCall 的相关性如何,因为它是提供 then 条件的调用者。
  • 我已经通过在异步调用周围包装承​​诺解决了我的问题。在答案中查看我的解决方案。

标签: javascript promise


【解决方案1】:

使用 async/await...它使处理 Promise(以及类似情况)变得更加容易,因为它使所有内容看起来都是同步的。

类似的东西。

const someFunction = async () => {
    const startTime = (+new Date());
    await someAsyncCall();
    const endTime = (+new Date());
    return [startTime, endTime]
}

另一个没有箭头函数和 const 的例子......

var someFunction = async function() {
    var startTime = (+new Date());
    await someAsyncCall();
    var endTime = (+new Date());
    return [startTime, endTime]
}

【讨论】:

  • +1 表示异步/等待。我认为这不会解决主要问题,如果他出于某种原因依赖.then,这仍然不会在then 方法调用之前触发。
  • @JonDeWitt 不会在 which then 方法调用之前触发?
  • 假设他想在他的承诺解决之后、.then() 方法被链接之前捕捉到这一刻。给定代码then 中只有一个位置可以链接,即someAsyncCall().then()。我仍然不确定我自己是否理解 OP 的问题。
  • 无论什么调用 someFunction 都期望得到一个承诺作为回报——我猜这是 async 提供的。但是,如果我不想将值返回给承诺怎么办?当您从这里归还它们时,它们会去哪里?最终,调用者不知道我试图环绕它以捕获开始和结束时间的代码。
【解决方案2】:

是的,只需在 someAsyncCall() 承诺上使用 then 回调。通过返回 Promise 链,someFunction 返回将使用您的回调结果解析的 Promise,随后将发生链接到它的进一步回调。

function someFunction() {
    var startTime = Date.now();
    return someAsyncCall().then(function() {
        var endTime = Date.now();
        return [startTime, endTime];
    });
}

someFunction().then(function(arr) {
    var [start, end] = arr;
    console.log(end - start);
});

【讨论】:

    【解决方案3】:

    好的,我想我现在明白你的问题了。为了等待一个承诺解决,并在不丢失数据的情况下返回另一个承诺,有一个使用混合技术的解决方案。让我们保留async/await,因为它们很漂亮。 :) 此外,我们可以将数据连同我们的 Promise 一起传递给resolve(),我们可以通过传递给then 的回调来使用它。运行下面的 sn -p 看看我的意思。

    // demo async call that takes 2 seconds to resolve
    const someAsyncCall = () =>
      new Promise(resolve => setTimeout(() => resolve(), 2000))
    
    const someFunction = async () => {
    
      // get the current time
      const startTime = Date.now()
      
      // wait for someAsyncCall() to resolve before moving on
      await someAsyncCall()
    
      // now that the async call has finished, get the time again
      const endTime = Date.now()
      
      // pass both start and end time as data to resolve
      // this is fed in as the first argument of the callback passed to .then()
      return Promise.resolve([startTime, endTime])
    }
    
    // the start and end time were passed from resolve()
    // access them from the first parameter of the callback passed to .then()
    someFunction().then(data => console.log(data))

    【讨论】:

      【解决方案4】:

      我通过创建自己的 Promise 并返回它来解决我的问题,而不是来自 someAsyncCall() 的 Promise。

      我基本上是从这个开始的:

      someFunction = function() {
          var startTime = (+new Date());
          return someAsyncCall();
          // How to capture endTime on then before moving on?
      };
      

      现在我有了这个:

      someFunction = function() {
          return new Promise(function(resolve, reject) {
              var startTime = (+new Date());
              someAsyncCall().then(function(response) {
                  var endTime = (+new Date());
                  // Record startTime and endTime here (code not shown)
                  resolve(response);
              }).catch(function(rtn) {
                  reject(rtn);
              });
          });
      };
      

      【讨论】:

        猜你喜欢
        • 2014-02-11
        • 2019-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-10
        • 1970-01-01
        • 2014-06-13
        相关资源
        最近更新 更多