如何在没有线程的情况下在Javascript中实现Promise

时间:2014-08-01 14:48:50

标签: javascript jquery promise

最近,我一直看到Promise的概念在AngularJS和JQuery中实现。

我已经在下面的代码中看到了Java中的Futures的实现,但是这需要在语言/平台中存在线程池的概念。但是,Javascript中没有这样的线程概念。如何实现Javascript中的Promise?

public class Futures1 {

    private static final ExecutorService pool = Executors
            .newFixedThreadPool(10);

    public static void main(String[] args) {

        Future<String> contentsFuture = null;
        try {
            contentsFuture = startDownloading(new URL("http://www.example.com"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        // other computation
        try {
            final String contents = contentsFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

    }

    public static Future<String> startDownloading(final URL url) {
        return pool.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                try (InputStream input = url.openStream()) {
                    return IOUtils.toString(input, StandardCharsets.UTF_8);
                }
            }
        });
    }
}

3 个答案:

答案 0 :(得分:31)

发明Promise是为了帮助管理异步操作,并且承诺自己不需要线程来实现这一点。它们本质上是为异步操作提供簿记的对象 - 保持状态转换的状态标志,结果值和监听器。这些都可以通过常规的单线程Javascript轻松完成。

因此,只要你有异步操作(但是这些操作已经实现),你就可以从承诺中受益,并且不需要线程来实现它们。

您在Java代码中看到的代码是帮助在单独的线程中运行常规任务的代码(为同步操作提供一些异步类型的行为)。这不是承诺所做的。因此,如果您已经在您的环境中进行了异步操作,那么您就不需要这种类型的代码来使用promises。

Javascript中异步事物的示例几乎是您注册的任何内容,实际事件将在未来的某个时间发生,其他代码可以在该事件触发之前运行。在浏览器的Javascript环境中,这包括setTimeout(),键盘事件,鼠标事件,ajax完成回调等等......这些都是异步事件。您注册了对它们的兴趣(通过注册事件监听器或将回调传递给某个函数)。在Javascript实现的内部,可能存在使这些异步事件工作的线程,但是这些线程不需要直接向程序员公开,以实现异步功能。例如,请参阅this post,了解Javascript如何在其他Javascript运行时在后台运行ajax调用。您需要知道的是,您的回调函数将在未来被称为某个不确定的时间。

因此,在Javascript中,promises用于管理环境中已存在的异步操作。它们不用于使非异步事物变得异步(为了做到这一点,你需要线程)。

请记住,promises本身只是监视工具,用于监视现有的异步操作。除.then()之外,Promise实际上并不是异步的,setTimeout()可以使用内置API实现,例如setImmediate()nextTick()或{{1}}。 Promise不需要自己的本机代码或线程。实际上,如果需要,可以在普通的单线程Javascript中编写promise实现。

答案 1 :(得分:2)

JavaScript层下面的浏览器编写的本机代码往往非常巧妙地实现了线程。事实证明,这通常是你所需要的。在JavaScript中执行实际的计算工作往往不需要Promise(虽然工作人员更容易),但是用于加载外部资源,并在完成后获得回调。 JS Promises只是将回调分配给像“image.onLoad”这样的函数,并检查是否通知另一个函数。

Hogan可能最好地总结了它 - 基于事件的编程。

答案 2 :(得分:0)

我认为Roamer-1888对OP的评论可能是将其他答案中的信息提炼成易于理解的关键。

以这种方式思考-Promise不提供异步性,但在处理其他方式提供的异步性方面在语法上很方便。 -漫游者1888

JS是单线程的,但是JS运行的环境可以利用其他线程。以浏览器为例:JS可以访问Web API(例如fetch),这些API允许它通过浏览器引擎在单线程JS环境之外(无论是网络环境)执行工作。请求,由网络工作者处理的事情,无论如何。承诺只是跟踪这些操作并在完成后接收其结果。