javascript - 在返回另一个函数的回调后调用一个函数

标签 javascript asynchronous callback

这是我的问题的简化版本:

var callback_one = function (result_from_web_service) {
  console.log('callback one');
};

var callback_two = function (result_from_web_service) {
 console.log('callback two');
};

// the async_calls are library calls that i don't own or modify
var x = function () {
  console.log('x is called');
  async_call_one(callback_one); 
  async_call_two(callback_two);
};

var y = function () {
 console.log('y is called');
};

Test:
x();
y();

// prints: 'x is called', 'y is called', 'callback one', 'callback two'
// what i need: 'x is called', 'callback one', 'callback two', 'y is called'

我所做的就是在 call_back_two 中调用 y():

var callback_two = function (result_from_web_service) {
   console.log('callback two');
   y();
};

但现在我的用例要求在回调之外调用 y(将由我的代码的用户调用)。即 x() 和 y() 的调用是独立的,x() 的调用不会最终调用 y()。 y() 应该被独立调用,但前提是 x() 及其回调被处理。将 x() 视为在 java 中创建一个对象,将 y() 视为您可以随时调用的方法。

//.. some code, x() does some kind of initialization...
x();

// OPTIONALLY call y(), but make sure x() and its callbacks are processed
y();

我尝试了以下方法,但没有用。

 $.when(x()).then(y());

谢谢,

最佳答案

使类似这样的东西正常工作的唯一方法是使 y 异步。基本上,y 在执行自己的代码之前会在内部等待 x 完成。这类似于 domreadyonload 之类的东西,它们在执行自己的逻辑之前等待其他事情发生。

有两种方法可以做到这一点。第一种最简单也是最天真的方法是 setTimeout 轮询。让 x 设置一个变量或属性并在执行前检查:

function y () {
    if (x.ready) {
        /* do what you need to do here */
    }
    else {
        setTimeout(y,100);
    }
}

第二种方法是创建虚拟事件或 promise 。并非所有 promise 库都支持使用已经过期的 promise (我自己自制的),因此您可能需要编写自己的控制流来处理这种情况。为此,您需要重写 x 以支持事件或类似 promise 的 api:

var x = (function () {
    var async_calls = 2;
    var callback;

    f = function () {
        console.log('x is called');
        async_call_one(function(){
            async_calls --;
            if (async_calls == 0 && callback) callback();
            callback_one();
        }); 
        async_call_two(function(){
            async_calls --;
            if (async_calls == 0 && callback) callback();
            callback_two();
        });
    }

    f.loaded = function (loaded_callback) {
        callback = loaded_callback;
        if (async_calls == 0) callback();
    }         

    return f;
})();

现在在 y 中,您可以使用 x.loaded 函数在加载 x 时执行您的代码:

function y () {
    x.loaded(function(){
        /* do what you need to do here */
    });
}

当然,这有让y异步的问题。因此,如果您的用户希望编写如下内容:

y();
a();
b();

然后 ab 可能会或可能不会在 y 之前执行。要解决这个问题,您需要让 y 接受回调,以便您的用户可以控制他们的程序流程:

function y (callback) {
    if (x.ready) {
        /* do what you need to do here */
        callback();
    }
    else {
        setTimeout(function(){y(callback)},100);
    }
}

或:

function y (callback) {
    x.loaded(function(){
        /* do what you need to do here */
        callback();
    });
}

所以他们必须像这样使用 y:

y(function(){
    a();
    b();
});

或者,如果您喜欢那种风格,您可以让 y 返回一个 promise。

关于javascript - 在返回另一个函数的回调后调用一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24540104/

相关文章:

javascript - 为什么在 jQuery 回调中检查变量是否存在会导致硬异常?

javascript - 如何在Web项目中像div标签一样使用View

javascript - 如何循环遍历嵌套的 JSON 数组以获取特定值?

c# - 我需要 MemoryBarrier 和 ReaderWriterLockSlim 吗?

swift - 在回调函数 swift 上展开一个 Optional 值

php - Grocery CRUD 回调函数如何工作?

javascript - Signalr 在服务器中托管 javascript 客户端的客户端脚本

javascript - backbone.js/从模型访问 View

asynchronous - 具有异步操作的面向铁路的编程

javascript - Node.js:使用顺序+异步输入/输出进行并行处理