什么是“回调地狱"?以及 RX 如何以及为什么解决它? [英] What is "callback hell" and how and why does RX solve it?

查看:25
本文介绍了什么是“回调地狱"?以及 RX 如何以及为什么解决它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能给出一个明确的定义,并举一个简单的例子来解释什么是不了解 JavaScript 和 node.js 的人的回调地狱"?

Can someone give a clear definition together with a simple example that explains what is a "callback hell" for someone who does not know JavaScript and node.js ?

回调地狱问题"什么时候(在什么样的设置下)发生?

When (in what kind of settings) does the "callback hell problem" occur?

为什么会发生?

回调地狱"总是与异步计算有关吗?

Is "callback hell" always related to asynchronous computations?

或者回调地狱"是否也会出现在单线程应用程序中?

Or can "callback hell" occur also in a single threaded application?

我参加了 Coursera 的响应式课程,Erik Meijer 在他的一次讲座中说 RX 解决了回调地狱"的问题.我在 Coursera 论坛上问什么是回调地狱",但我没有得到明确的答案.

I took the Reactive Course at Coursera and Erik Meijer said in one of his lectures that RX solves the problem of "callback hell". I asked what is a "callback hell" on the Coursera forum but I got no clear answer.

在用一个简单的例子解释了回调地狱"之后,你能不能在这个简单的例子上展示 RX 如何解决回调地狱问题"?

After explaining "callback hell" on a simple example, could you also show how RX solves the "callback hell problem" on that simple example?

推荐答案

1) 对于不懂 javascript 和 node.js 的人来说,什么是回调地狱"?

另一个问题有一些Javascript回调地狱的例子:如何避免Node.js中异步函数的长嵌套

Javascript 中的问题是冻结"计算并让其余部分"在后面(异步)执行的唯一方法是将其余部分"放入回调中.

The problem in Javascript is that the only way to "freeze" a computation and have the "rest of it" execute latter (asynchronously) is to put "the rest of it" inside a callback.

例如,假设我想运行如下所示的代码:

For example, say I want to run code that looks like this:

x = getData();
y = getMoreData(x);
z = getMoreData(y);
...

如果现在我想让 getData 函数异步,这意味着我有机会在等待它们返回值的同时运行一些其他代码,会发生什么?在 Javascript 中,唯一的方法是使用 延续传球风格:

What happens if now I want to make the getData functions asynchronous, meaning that I get a chance to run some other code while I am waiting for them to return their values? In Javascript, the only way would be to rewrite everything that touches an async computation using continuation passing style:

getData(function(x){
    getMoreData(x, function(y){
        getMoreData(y, function(z){ 
            ...
        });
    });
});

我不认为我需要说服任何人这个版本比前一个更丑.:-)

I don't think I need to convince anyone that this version is uglier than the previous one. :-)

当你的代码中有很多回调函数时!您的代码中使用它们的次数越多,使用它们就越困难,并且当您需要执行循环、try-catch 块和诸如此类的事情时,情况尤其糟糕.

When you have lots of callback functions in your code! It gets harder to work with them the more of them you have in your code and it gets particularly bad when you need to do loops, try-catch blocks and things like that.

例如,据我所知,在 JavaScript 中执行一系列异步函数的唯一方法是使用递归函数.您不能使用 for 循环.

For example, as far as I know, in JavaScript the only way to execute a series of asynchronous functions where one is run after the previous returns is using a recursive function. You can't use a for loop.

// we would like to write the following
for(var i=0; i<10; i++){
    doSomething(i);
}
blah();

相反,我们可能需要写成:

Instead, we might need to end up writing:

function loop(i, onDone){
    if(i >= 10){
        onDone()
    }else{
        doSomething(i, function(){
            loop(i+1, onDone);
        });
     }
}
loop(0, function(){
    blah();
});

//ugh!

我们在 StackOverflow 上收到的询问如何做这种事情的问题的数量证明了它是多么令人困惑:)

The number of questions we get here on StackOverflow asking how to do this kind of thing is a testament to how confusing it is :)

发生这种情况是因为在 JavaScript 中延迟计算以使其在异步调用返回后运行的唯一方法是将延迟代码放入回调函数中.您无法延迟以传统同步方式编写的代码,因此您最终会在各处使用嵌套回调.

It occurs because in JavaScript the only way to delay a computation so that it runs after the asynchronous call returns is to put the delayed code inside a callback function. You cannot delay code that was written in traditional synchronous style so you end up with nested callbacks everywhere.

异步编程与并发有关,而单线程与并行有关.这两个概念其实不是一回事.

Asynchronous programming has to do with concurrency while a single-thread has to do with parallelism. The two concepts are actually not the same thing.

您仍然可以在单线程上下文中拥有并发代码.事实上,回调地狱的女王 JavaScript 是单线程的.

You can still have concurrent code in a single threaded context. In fact, JavaScript, the queen of callback hell, is single threaded.

并发和并行有什么区别?

我对 RX 一无所知,但通常这个问题可以通过在编程语言中添加对异步计算的本机支持来解决.实现可能会有所不同,包括:异步、生成器、协同程序和 callcc.

I don't know anything about RX in particular, but usually this problem gets solved by adding native support for asynchronous computation in the programming language. The implementations can vary and include: async, generators, coroutines, and callcc.

在 Python 中,我们可以使用以下内容来实现前面的循环示例:

In Python we can implement that previous loop example with something along the lines of:

def myLoop():
    for i in range(10):
        doSomething(i)
        yield

myGen = myLoop()

这不是完整的代码,但其想法是yield"会暂停我们的 for 循环,直到有人调用 myGen.next().重要的是,我们仍然可以使用 for 循环编写代码,而无需像在递归 loop 函数中那样由内而外"转换逻辑.

This is not the full code but the idea is that the "yield" pauses our for loop until someone calls myGen.next(). The important thing is that we could still write the code using a for loop, without needing to turn out logic "inside out" like we had to do in that recursive loop function.

这篇关于什么是“回调地狱"?以及 RX 如何以及为什么解决它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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