返回另一个函数的回调后调用一个函数 [英] Calling a function after another function's callbacks are returned

查看:133
本文介绍了返回另一个函数的回调后调用一个函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我问题的简化版本:

This is the simplified version of my problem:

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():

What I did to accomplish this was calling y() inside call_back_two:

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

但是现在我的用例要求在回调之外调用y(将由用户调用我的代码)。即x()和y()的调用是独立的,因此x()的调用不会最终调用y()。 y()应该独立调用,但仅当x()及其回调被处理时才应调用。认为x()就像在java中创建对象,而y()则是您可以随时调用的方法。

But now my use case requires that y be called outside of the callback (will be called by the user of my code). i.e. the calling of x() and y() be independent in a way that the calling of x() doesn't end up calling y(). y() should be called independently but only if x() and its callbacks are processed. think of x() as like creating an object in java and y() as a method you would call whenever you want.

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

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

我尝试了以下操作,但不起作用。

I tried the below but doesn't work.

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

谢谢,

推荐答案

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

The only way to make something like this work properly is to make y asynchronous. Basically, y internally waits for x to complete before executing its own code. This is similar to things like domready or onload which waits for other things to happen before executing their own logic.

有两种方法可以完成此操作。第一种,最简单也是最幼稚的方式是 setTimeout 轮询。使 x 设置一个变量或属性,并在执行之前进行检查:

There are two ways to accomplish this. The first, simplest and most naive way is setTimeout polling. Make x set a variable or attribute and check that before executing:

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

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

The second method is to create virtual events or promises. Not all promise libraries support using a promise that has already expired (my own homemade one does) so you may need to write your own control flow to handle that case. For this you need to rewrite x to support an event or promise-like 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时执行代码:

Now in y you can use the x.loaded function to execute your code when x is loaded:

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

当然,这会导致 y 异步。因此,如果您的用户希望写这样的东西:

Of course, this has the problem of making y asynchronous. Therefore if your users expect to write something like:

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

然后 a b 可能会在 y 之前执行,也可能不会执行。要解决此问题,您需要使 y 接受回调,以便用户可以控制其程序流:

then a and b may or may not execute before y. To solve this you need to make y accept a callback so that you users can control their program flow:

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

or:

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

所以他们不得不使用 y 像这样:

So they'd have to use y like this:

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

或者,您可以使 y 返还承诺如果您喜欢这种风格。

Alternatively you can make y return a promise if you prefer that style.

这篇关于返回另一个函数的回调后调用一个函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆