Как приостановить функцию в JavaScript?

У меня есть длинная функция в JavaScript, и я собираюсь приостановить ее в некоторых моментах. Я знаю, что могу сделать это, используя setTimeout(myFunction, 100) и clearTimeout(). Но, как я знаю, после использования setTimeout(myFunction, 100) моя функция будет выполняться с первой строки через 100 миллисекунд, а затем каждые 100 миллисекунд. Мне интересно, могу ли я приостановить свою функцию в строке 50, а затем возобновить ее сразу после этой строки, которая равна 51. Возможно ли это?


person Suo6613    schedule 19.10.2014    source источник
comment
Пожалуйста, предоставьте нам некоторый код, чтобы мы могли дать более точные ответы.   -  person Aadit M Shah    schedule 19.10.2014
comment
Вы также можете захотеть увидеть веб-воркеров, если вы просто делаете расчеты. html5rocks.com/en/tutorials/workers/basics   -  person GramThanos    schedule 19.10.2014
comment
Я думаю, что function* — это то, что вы хотите. Для функции, совместимой с es5, вы можете смоделировать yield по регистру переключателей.   -  person Herrington Darkholme    schedule 19.10.2014
comment
Спасибо, что помогли мне правильно сформулировать мой вопрос, а также за ссылку. Я только что сделал комментарий под вторым ответом. ваши комментарии там будут оценены.   -  person Suo6613    schedule 19.10.2014
comment
Здесь нельзя сделать ничего, что само по себе не создает дополнительных причуд и не входит в область асинхронного программирования. Например, код, разделяющий функцию на две части и дважды вызывающий setTimeout, вернется и продолжит работу. setTimeout только графики. Сам он ничего не вызывает и не выполняет. Если другой код написан, чтобы предположить, что две части завершены, потому что функция возвратила, это становится ошибкой. Это не делает ответы неправильными. Это подчеркивает необходимость изучения того, как работает цикл обработки событий Javascript, что такое асинхронное программирование, почему в JS нет функции sleep().   -  person Paul    schedule 24.10.2014
comment
Большое спасибо @Paul за комментарий.   -  person Suo6613    schedule 26.10.2014


Ответы (2)


Вот один из способов сделать это. Убедитесь, что все переменные, которые вам всегда нужны, объявлены во внешней функции. Из-за правил области действия Javascript они будут доступны в каждой подфункции.

function paused() {
  // Define variables you'll need throughout the function.
  var var1, var2, var3;

  // First part of the function
  function part1() {
    // 50 lines
  }

  // Second part of the function
  function part2() {
    // 50 lines
  }

  setTimeout(part1, 0);
  setTimeout(part2, 100);
}

Предположим, что есть много частей, тайм-ауты можно даже зациклить:

function paused() {
  // Define variables you'll need throughout the function.
  var var1, var2, var3;

  // All function parts.
  var parts = [
    function() {
      // 50 lines
    },
    function() {
      // 50 lines
    },
    function() {
      // 50 lines
    }
    // More?
  ];

  for (var i = 0; i < parts.length; i++) {
    setTimeout(parts[i], i * 100);
  }
}

Обязательно будьте осторожны при использовании this, так как внутренние функции перепривязывают его.

Обратите внимание, что глобальная функция всегда будет выполнять приостановленные части по порядку, независимо от того, занимает ли каждая отдельная часть более 100 мс, из-за того, как работает очередь событий Javascript. Когда очередь событий видит, что несколько setTimeouts могут быть выполнены одновременно, приоритет отдается первому из них.

person Fengyang Wang    schedule 19.10.2014
comment
var function paused, безусловно, интересно попробовать расшифровать как английский, но это неверный JavaScript. :) (у вас есть дополнительные var в начале каждого из ваших блоков кода) - person tckmn; 19.10.2014
comment
если для выполнения какой-либо части требуется более 100 мс, глобальная функция сломается. - person rnrneverdies; 19.10.2014
comment
Он мог вставлять каждый setTimeout внутрь другого. - person GramThanos; 19.10.2014
comment
@Deuterium: модель событий Javascript будет выполнять тайм-ауты в порядке очереди, а тайм-ауты ставятся в очередь в естественном порядке. Так что это не забота. Если в одном и том же кадре вызовов выполняются два вызова setTimeout — передача того же значения для второго аргумента — их обратные вызовы будут поставлены в очередь в порядке вызова. - person Fengyang Wang; 19.10.2014
comment
@FengyangWang ... о, хорошо! танки для обучения! я все еще думаю на С++ .. извините. - person rnrneverdies; 19.10.2014
comment
Этот код освобождает неосторожного джинна асинхронного программирования. Хотя может показаться, что этот код отвечает на вопрос OP, я думаю, что этот код может не работать с другим кодом, который предполагает, что обе части функции выполняются, когда функция возвращается. - person Paul; 24.10.2014

Вы путаете setTimeout и setInterval.

Однако это совершенно невозможно.

Вместо этого вам нужно разбить его на две функции, и вызвать вторую из первой с помощью setTimeout.

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

person SLaks    schedule 19.10.2014
comment
Как ОП путает setTimeout и setInterval? То, что хочет сделать ОП, не является невозможным. Вы можете использовать генераторы, чтобы приостановить функцию на полпути. Я не понимаю, как обещания могут помочь. Этот ответ не добавляет ничего ценного. Вместо этого должен быть комментарий. - person Aadit M Shah; 19.10.2014
comment
ОП использовал тег setinterval. Возможно, это можно было бы исправить. - person Fengyang Wang; 19.10.2014
comment
@Aadit M Shah - Что ж, если вы прочитаете это еще раз, вы увидите, что он путает setTimeout и setInterval. - person GramThanos; 19.10.2014
comment
@ThanasisGrammatopoulos Нет, это не так. Если вы вызываете setTimout(foo, 100) внутри функции foo, то вы вызываете setTimeout рекурсивно, что означает, что foo будет вызываться каждые 100 миллисекунд. Это определенно не то же самое, что setInterval. Однако ОП должен был уточнить какой-то код. - person Aadit M Shah; 19.10.2014
comment
Похоже ты прав... :/ - person GramThanos; 19.10.2014
comment
Большое Вам спасибо. Я думаю, да, я запутался в этих вещах и был бы признателен, если бы вы, ребята, могли мне помочь. На самом деле, я использую PhantomJS для сканирования веб-сайта. У меня куча функций. Я хочу остановить все свои функции сразу после запуска каждого запроса и возобновить свою функцию (сразу после строки, на которой я остановил свои функции) после получения всех ответов. Поэтому я не знаю, какая функция вызовет следующий запрос. Я не хочу, чтобы мои функции выполнялись каждые 100 миллисекунд. Я имею в виду, я не хочу никаких задержек здесь. - person Suo6613; 19.10.2014
comment
Но, используя ваше определение, кажется, что я использую здесь задержку. У меня слишком много строк кода, и я не знаю, какая часть может помочь мне лучше объяснить мой вопрос. Ясен мой вопрос или вам нужно, чтобы я объяснил его по-другому? - person Suo6613; 19.10.2014
comment
Чтобы уточнить, у меня есть основная функция. скажем, «myFunction», и я вызываю другие свои функции внутри «myFunction». Затем я могу приостановить «myFunction», используя «setTimeout», но я хочу возобновить его именно из функции, которая вызвала его остановку! - person Suo6613; 19.10.2014
comment
@ Suo6613: Вы не можете приостановить функцию. Вы должны использовать обещания, чтобы дождаться получения ответов, как только они вам понадобятся. - person SLaks; 19.10.2014
comment
Спасибо @SLaks за комментарий. - person Suo6613; 19.10.2014