Борьба с обещаниями - как сделать что-то во внутреннем, прежде чем будет вызвано внешнее? - PullRequest
0 голосов
/ 10 октября 2019

Не знаю, как задать этот вопрос, и я действительно борюсь с обещаниями, поэтому я попробую на упрощенном примере.

Скажем, у меня есть функция, которая принимает обратный вызов. В этой функции я хочу сделать асинхронный вызов, который также имеет обратный вызов, поэтому, когда вызывается его обратный вызов, я делаю что-то на основе его ответа, а затем вызываю свой обратный вызов.

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

Что делает функцияне имеет значения, так как меня интересует структура и последовательность вещей. Но этот пример просто записывает время до и после выполнения внутреннего асинхронного вызова, а затем вызывает обратный вызов, чтобы сообщить эту информацию.

Теперь, на мой вопрос, допустим, что someAsyncCall был преобразован в Promise, а someFunctionтакже преобразуется, чтобы вернуть это обещание и не принимает обратный вызов. Итак, структурно моя функция теперь будет выглядеть примерно так:

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

Проблема в том, что теперь я хочу захватить время окончания после someAsyncCall () и записать эти данные где-то, предположительно на то времяусловие someAsyncCall (), перед тем как вызывается условие someFunction (). Как мне это сделать?


ОБНОВЛЕНИЕ: Мне кажется, я не получаю ответ, который ищу, или просто не могу понять, что у меня в голове, так что, возможно, лучший способсформулируйте мой вопрос следующим образом:

Давайте начнем с этого примера кода:

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

В конечном счете, doProcess возвращает обещание, которое возвращается startProcess. Затем вызывающая сторона делает с ней все, что делает.

Теперь я хочу обернуть некоторый код в doProcess, чтобы зафиксировать время начала и окончания, без каких-либо помех работе существующего кода. Есть ли какой-нибудь способ, которым я могу ответить на завершение doProcess, чтобы сделать что-то, прежде чем он разрешит обещание, обычно для того, что вызывает startProcess? Дело в том, что эта функция не имеет ни малейшего представления, кто ее вызывает или что делает вызывающая сторона с обещанием;по сути, это просто оболочка для doProcess.

Ответы [ 4 ]

1 голос
/ 10 октября 2019

Используйте async / await ... это значительно облегчает работу с обещаниями (и подобными ситуациями), потому что все читается как синхронно.

Примерно так.

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

Еще один пример без функций со стрелками и констант ...

var someFunction = async function() {
    var startTime = (+new Date());
    await someAsyncCall();
    var endTime = (+new Date());
    return [startTime, endTime]
}
0 голосов
/ 12 октября 2019

Я решил свою проблему, создав собственное обещание и возвратив его вместо обещания, которое исходило от someAsyncCall ().

Я начал с этого, по сути:

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);
        });
    });
};
0 голосов
/ 10 октября 2019

Ладно, теперь я понимаю ваш вопрос. Чтобы дождаться выполнения обещания, а также вернуть другое обещание без потери данных, существует решение, использующее сочетание различных методов. Давайте сохраним async/await, потому что они прекрасны. :) Кроме того, мы можем отправить данные вместе с нашим обещанием, передав их в resolve(), и мы можем использовать их через обратные вызовы, переданные в then. Запустите фрагмент ниже, чтобы понять, что я имею в виду.

// 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))
0 голосов
/ 10 октября 2019

Да, просто используйте обратный вызов then для обещания someAsyncCall(). Возвращая цепочку обещаний, someFunction возвращает обещание, которое разрешится с вашими результатами обратного вызова, и последующие обратные вызовы, связанные с ним, произойдут впоследствии.

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);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...