Возврат для функции после определенного времени выполнения - PullRequest
0 голосов
/ 07 мая 2019

Полная ясность, я делаю это в Узле, если это имеет значение.

У меня есть метод, который делает несколько синхронных вызовов (они зависят от обратной связи каждого вызова в следующем, поэтому должны быть синхронными), и я не контролирую окружающую среду или вещи, которые я вызываю.

Мне нужно вернуть значение через заданное время (около 3 секунд), независимо от того, были ли завершены эти вызовы. Если эти вызовы завершены, скрипт завершает работу и возвращает значение. Этакий тайм-аут резервного копирования, который возвращает допустимое (если не полное) значение вместо полного тайм-аута из-за ограничений на выполнение сервера и выдачи ошибки.

Я сразу же думаю использовать setTimeout()clearTimeout(), если он не сработал) для возврата. Однако возвращение значения в обратном вызове setTimeout не завершает мой сценарий и, очевидно, возвращает это значение - так как бы я?

//"myFunction" being consumed by something I don't have control over
//Otherwise I'd just wrap the caller in a timeout
myFunction = async () => {

    var scripttimer = setTimeout(function(){
        //emergency exit - script took longer than 3 seconds
        return "I need to return a value for myFunction now"; 
    }, 3000);

    //multiple synchronous remote https calls are made
    //right here which could sometimes cause this function
    //to take more than 3 seconds, at which point the 
    //scripttimer should kill myFunction by making it return 
    //a value. That's the part that I'm asking how to do, if 
    //even possible

    if (scripttimer){
        //if we took less than 3 seconds, we don't need the backup 
        //callback in scripttimer and so we're going to kill it
        clearTimeout(scripttimer);
    }

    //best scenario return value, script took less than 3 seconds
    return "did this anyways";
}

Пытались

Мысль сделать настройку трик-бросок-бросок:

try {

    var scripttimer = setTimeout(function(){
        throw "I need to return a value for myFunction now"; 
    }, 3000);

    //wait 4 seconds maybe
    if (scripttimer){
        clearTimeout(scripttimer);
    }
    return "I don't make it out if I take too long";


} catch (e){
    return "acceptable enough";
}

... но перехватчик не улавливает его, что имеет смысл, поскольку выбрасываемая ошибка выходит за рамки попытки перехвата, поскольку она асинхронна ... так что пока что моя лучшая идея до сих пор.

Ответы [ 2 ]

2 голосов
/ 09 мая 2019

Если вы измените задержку в функции httpCall менее чем на 3 секунды, то вы получите вывод как hello

и если задержка в httpCall превышает 3 секунды, вы получите вывод как bye

// Your Http Call Here which may take 3 seconds or more. eg.5 seconds


function httpCall(){
  return new Promise((resolve,reject)=>{
    setTimeout(function(){
        resolve("hello")
    },5000)
  });
}

// your main function where you will be calling sync functions
function operation(){
  return new Promise((resolve,reject)=>{
    const timeoutID = setTimeout(function(){
        resolve("bye")
    },3000)
    httpCall().then(result=>{
       clearTimeout(timeoutID)
       resolve(result)
    })
  });
}

// This is how you should call
operation().then((result)=>console.log(result))

Проверьте выполнение здесь

1 голос
/ 07 мая 2019

На самом деле setTimeout не работает так же, как цикл событий узла js.

С вашей реализацией выше, обратный вызов в setTimeout никогда не будет вызываться, потому что clearTimeout будет выполняться почти сразу. SetTimeout во время обратного отсчета позволит выполнить последующий код в скрипте, что означает, что clearTimeout будет вызван немедленно, потому что переменная scripttimmer верна.

Еще одна вещь, на которую следует обратить внимание: вы должны использовать clearTimeout, только если вы планируете помешать setTimeout выполнить его обратный вызов.

Вы можете попробовать реализацию с обратным вызовом, который позволит вам взаимодействовать с возвращаемой переменной следующим образом:

const myFunction = async callback => {
    var scripttimer = setTimeout(function(){
        callback("my value");
    }, 3000);

    return "did this anyways";
}

myFunction(val => console.log(val));

См. Исполнение здесь

Кроме того, вам следует избегать использования async, если только вы не планируете использовать await в своей функции.

...