简体   繁体   English

获取当前运行异步 function 的结果

[英]Get result of currently running async function

How to check if there is already running function and if it is exist listen to this function result;如何检查是否已经运行 function 以及是否存在,请听此 function 结果;

async function a() {
// wait 5 seconds and return foo = foo + 1;
// if A is already running await and return result of this running function A instead result;
}

If I translate the problem correctly, A returns a promise that is asynchronously settled.如果我正确翻译问题, A返回一个异步解决的 promise。 While the promise is pending, all calls to a wrapper function around A should return the currently pending promise.虽然 promise 处于挂起状态,但对围绕A的包装器 function 的所有调用都应返回当前挂起的 promise。

If, however, A has not been called, or a previously return promise has been settled, A should be called again.但是,如果 A 没有被调用,或者之前返回的 promise 已经解决,则应该再次调用 A。

This can be achieved by chaining off the promise returned by A, using promise handlers to determine results are no longer pending, and have the wrapper function return the chained promise. This can be achieved by chaining off the promise returned by A, using promise handlers to determine results are no longer pending, and have the wrapper function return the chained promise. This example code speeds up the process a little - four successive calls made to a 500ms apart get the same fulfilled value from A which is taking 2000ms to perform a mythical asynchronous task:这个示例代码稍微加快了这个过程——相隔 500 毫秒a四个连续调用从A获得相同的已实现值,这需要 2000 毫秒来执行一个神话般的异步任务:

 // promise a delay const delay = ms => new Promise(resolve=>setTimeout(resolve, ms)); // async function A let foo =0; async function A() { await delay( 2000); // 2 second example return foo = foo + 1; } // Wrapper function a let a; { // block scoped let promiseA; a = ()=> { return promiseA? promiseA: promiseA = A().then( data => { promiseA=null; return data }, err => { promiseA=null; throw err} ); } } // and test async function test() { for( let i=1; i < 11; ++i) { a().then( data=> console.log(`a() call ${i} fulfills with ${data}`)); await delay(500); } } test();

  • The code block enclosed by { and } gives the let variable block scope and makes it invisible from outside.{}包围的代码块给出了let变量块 scope 并使其从外部不可见。 Other solutions are possible.其他解决方案是可能的。
  • The then call uses the two parameter form for brevity.为了简洁起见, then调用使用两个参数形式。
  • The catch handler re-throws the error for caller code to handle. catch 处理程序重新抛出错误以供调用者代码处理。
  • synchronous and asynchronous code don't mix well together.同步和异步代码不能很好地混合在一起。 Calls to the wrapper function a always receive a promise value in return - although sometimes it's pending, sometimes not.对包装器 function a调用总是会收到 promise 值作为回报 - 尽管有时它处于未决状态,但有时不是。

Solution解决方案
You can create class that will be execute one flow (maximum) and await result if flow already running.您可以创建 class 将执行一个流(最大)并在流已经运行时等待结果。 It may looks something like that:它可能看起来像这样:

class OneThreadExecutor {

    // Boolean variable which represents is task running right now
    taskRunning = false;

    // All Promise.resolve callbacks
    listeners = [];

    // Accept initial value
    constructor(value = 0) {
        this.value = value;
    }

    // Send [result = value + 1] after 5 sec
    startNewTask = () => {
        this.taskRunning = true;
        setTimeout(() => {
            this.taskRunning = false;
            return this.sendResult();
        }, 5000)
    }

    // Call all Promise.resolve callbacks, and pass [value + 1] to them
    sendResult = () => {
        for (const listener of this.listeners) {
            listener(++this.value);
        }
        this.listeners = [];
    }

    // Main method that exec one task
    getResult = () => new Promise(resolve => {
        // Add callback to queue
        this.listeners.push(resolve); 
        // Start new task if necessary
        if (!this.taskRunning) this.startNewTask(); 
    })

}

General concept一般概念
Async getResult method will register promise in class' queue.异步getResult方法将在类队列中注册 promise。 Any successfull task execution will send result to queue.任何成功的任务执行都会将结果发送到队列。 Current task returns value + 1 on each getResult call and take 5 seconds for whole flow.当前任务在每个getResult调用上返回value + 1 ,整个流程需要 5 秒。

Usage用法

const a = new OneThreadExecutor(); // value = 0 by default

// will start task#1, 5 sec left till .then call, value = 1
a.getResult().then(...)
// 2.5 sec left, task#1 is already half progress, value = 2 
setTimeout(() => {
    a.getResult().then(...) 
}, 2500)

Async/await异步/等待


const a = new OneThreadExecutor(3); // let's set value = 3 initially

// will start task#1, 5 sec left till .then call, value = 4
a.getResult();
// wait till task#1 completed, 5 sec left, value = 5 
const value = await a.getResult();
// will start task#2 bacause not task running, 5 sec left, value = 6 
a.getResult();

Cons缺点
In demo solution we already expect successful task execution, without error handling, so you may need to extend it for proper error catching during task execution.在演示解决方案中,我们已经期望成功的任务执行,没有错误处理,因此您可能需要扩展它以在任务执行期间正确捕获错误。

var is_a_running = false;
function a() {
    if (is_a_running == false) {
        is_a_running = true
        //do something
        //after you have done the thing
        is_a_running = false
    }
    else if (is_a_running == true){
        result();
    }
}

This is should help you这应该可以帮助你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM