Asynchronous function in a while-loop

I have a question about how to perform an asynchronous task in a while-loop until some condition is met. This is more of a theoretical question but I can see how this could be an issue in some scenarios.

I‘ll try demonstrate the problem at an example (I‘m using JavaScript here, but you can use any language):

I could have a device and I want to hold my application until that device has reached a specific state. If the method with which I can getrieve with state of the device is synchronouse, the code could look like this:

// Hold until the desired state is reached
var state = false;
while (!state) {
    state = device.getStateSync();
}
// [...] continue the program

My question now is: How can I transform this code when all I get from the device is a asynchronous getState function? The code should work no matter how long the execution time of the call is and should keep in mind that I‘m working on limited memory and stack size.

// [...] This would call the async function in a loop and crash the program
while (!state) {
    // [...] something
    device.getStateAsync(function(newState) {
        state = newState;
    });
    // [...] something else
}

This one post that I found has a recursive solution (http://blog.victorquinn.com/javascript-promise-while-loop). While this is a nice solution, at some point it will run into stack-size problems, if the loop is called too often.

Right now I have the gut feeling that there might be no solution. Do you know of any way to do this? Or do you know how to prove that there is no way to do it? Feel free to include more complex concepts like Threads, Promises or Futures.

Please bear in mind, that this is a theoretical question and the example is for a situation where I have no way of changing the framework (or device) I am working with.

Thanks for every response and idea!

Pedro

   

Don‘t use a while loop. Just have the callback invoke the getStateAsync until the state should disallow it. There‘s no call stack size issue at all. – cookie monster Aug 15 ‘14 at 23:05 
    

...and I don‘t see why you‘d think there‘ll be a stack size issue in the code you linked. It‘s using a promise library and making asynchronous calls. – cookie monster Aug 15 ‘14 at 23:13

In javascript, you cannot loop waiting for a condition to change unless the code that actually changes the condition is inside that very loop or a side effect of some function called in the loop. That‘s because javascript is single threaded (except for webworkers which aren‘t being considered here) so as long as a loop is looping in javascript, no other code can run so no other code can ever change your condition variable. You will simply have an infinite loop as the loop waits for something that can never change. Eventually the browser will complain that you have unresponsive code running and shut it down.

Because of that, there aren‘t indeterminate or long wait loops in javascript. It is possible to loop for a second or so just to let some time pass, but that‘s rarely useful, productive or the best way to write JS code.

Instead, you have to either trigger an event or callback when the condition changes and the interested code can subscribe to that event or register its callback. Or, you have to poll on a timer to see what the condition has changed (the first option is the preferred choice).



If you were designing an API where you wanted to be able to allow some calling code to know when a state changes, usually you would implement either a callback or a promise. The callback approach could look like this:

device.registerStateChangeCallback("type of state interested in", fn);

Then, the API will call the passed in callback function whenever the specified state changes to a new value. It‘s up to the API whether this is a one-time notification or whether it happens every time the state changes until the callback is deregistered.

So, rather than having the caller wait in a busy loop until the state changes, the caller writes async code (this is how javascript works for this kind of stuff) with a callback that will be called sometime later when the state changes. For example, a caller‘s code might look like this:

device.registerStateChangeCallback("syncState", function(newState) {
     // caller puts code here that wants to do something when
     // the syncState has changed
});


If the notifications are meant to be one time only, then you could also use promises and the API simply returns a promise that is resolved when the syncState changes:

device.registerStateChange("syncState").then(function(newState) {
     // caller puts code here that wants to do something when
     // the syncState has changed
});

The disadvantages of promises are that they are purely single use (one notification only) so if you want multiple notifications, then better to use callbacks. The advantages of promises over callbacks is that they provide a lot of features for synchronizing them with other events (such as sequencing, waiting for a series of events to all finish, coordinating multiple async things, etc...) and they provide better async error handling.

——————————————————————————————————————————————————

You can‘t do this. The reason is that Javascript is single-threaded. While the while loop is running, nothing else runs, so whatever asynchronous task is expected to update the device state will never get a chance to run. Asynchronous tasks in Javascript are run by the main event handler loop. This means that asynch operations won‘t run until you return from your script back to the event handler, or the script performs a call into the event handler (this only happens when the script waits for user input with confirm or prompt).

——————————————————————————————————————————————————————————————————————————————

This is indeed a very theoretical question. It would be quite weird to have an async API to get a current status. You would most probably have either:

  • a sync method that gives you the current status;
  • or an async method that would call you back when the status changes. In that case, no need to loop, you just wait for the callback.

But if you do have a specific example of such an API, let us know...

http://stackoverflow.com/questions/25335203/asynchronous-function-in-a-while-loop

时间: 2024-10-16 06:38:45

Asynchronous function in a while-loop的相关文章

AsyncCalls – Asynchronous function calls

AsyncCalls – Asynchronous function callsWith AsyncCalls you can execute multiple functions at the same time and synchronize them at every point in the function or method that started them. This allows you to execute time consuming code whos result is

gevent: AssertionError: Impossible to call blocking function in the event loop callback

今天在用爬虫时gevent报了AssertionError: Impossible to call blocking function in the event loop callback 异常,很奇怪,难道是patch_socket惹的货,因为之前没有使用patch_socket是正常的,代码简化如下 import urllib import gevent from gevent.monkey import patch_socket from gevent.hub import get_hub

5 jQuery.each() Function Examples

OK, this is quite an extensive overview of the jQuery .each() function. This is one of jQuery’s most important and most used functions so that’s the reason why I’ve chosen to go into such detail about it and really get down and dirty about how to use

理解callback function in javascript

以下内容主要摘自[1,2] (1)In javascript, functions are first-class objects, which means functions can be used in a first-class manner like objects, since they are in fact objects themselves: They can be “stored in variables, passed as arguments to functions,

[GIF] GIF Loop Coder - Animating with Arrays

In this lesson, we discuss animating using arrays, and how different data types are interpolated while animating. function onGLC(glc) { glc.loop(); // glc.size(400, 400); // glc.setDuration(5); // glc.setFPS(20); // glc.setMode('single'); // glc.setE

[GIF] GIF Loop Coder - Introduction

Introducing the program, GIF Loop Coder, which allows you to make looping animated gifs (and other types of animations) using JavaScript and HTML5 Canvas. We'll cover the basic UI and syntax of how to add objects to the animation list, animate them a

Tornado学习记录二

Coroutines Coroutines are the recommended way to write asynchronous code in Tornado. Coroutines use the Python yield keyword to suspend and resume execution instead of a chain of callbacks (cooperative lightweight threads as seen in frameworks like g

async源码学习 - 全部源码

因为工作需要,可能我离前端走远了,偏node方向了.所以异步编程的需求很多,于是乎,不得不带着学习async了. 我有个习惯,用别人的东西之前,喜欢稍微搞明白点,so就带着看看其源码. github: https://github.com/caolan/async 文档:http://caolan.github.io/async/ 里面提供的工具方法,控制流程方法还是很多的.所以需要哪些方法,就看相应的源码. 下面是其全部源码. (function (global, factory) { typ

Chromium Embedded Framework 中文文档(简介)

转自:http://www.cnblogs.com/think/archive/2011/10/06/CEF-Introduce.html 简介 Chromium Embedded Framework (CEF)是由 Marshall Greenblatt 在2008年创办的开源项目,致力于基于Google Chromium项目开发一个Web控件. CEF目前已支持多种编程语言和操作系统,能方便地集成到现有或者新的应用程序中,设计上,它追求高性能的同时,也追求易于使用,它的基本框架通过原生库提供