那么()函数在JavaScript中是什么意思?

2022-08-29 23:48:10

我一直看到这样的代码:

myObj.doSome("task").then(function(env) {
    // logic
});

从何而来?then()


答案 1

在JavaScript中处理异步调用的传统方法是使用回调。假设我们必须对服务器进行三次调用,一个接一个地设置我们的应用程序。使用回调时,代码可能如下所示(假设使用 xhrGET 函数进行服务器调用):

// Fetch some server configuration
    xhrGET('/api/server-config', function(config) {
        // Fetch the user information, if he's logged in
        xhrGET('/api/' + config.USER_END_POINT, function(user) {
            // Fetch the items for the user
            xhrGET('/api/' + user.id + '/items', function(items) {
                // Actually display the items here
            });
        });
    });

在此示例中,我们首先获取服务器配置。然后,基于此,我们获取有关当前用户的信息,然后最终获取当前用户的项目列表。每个 xhrGET 调用都采用一个回调函数,该函数在服务器响应时执行。

当然,现在我们的嵌套级别越多,代码就越难读取、调试、维护、升级和基本使用。这通常被称为回调地狱。此外,如果我们需要处理错误,我们可能需要将另一个函数传递给每个xhrGET调用,以告诉它在发生错误时需要做什么。如果我们只想有一个常见的错误处理程序,那是不可能的。

Promise API旨在解决此嵌套问题和错误处理问题。

Promise API 提出了以下建议:

  1. 每个异步任务将返回一个对象。promise
  2. 每个对象都有一个函数,该函数可以采用两个参数,一个处理程序和一个处理程序。promisethensuccesserror
  3. 在异步任务完成后,函数中的成功错误处理程序将仅调用一次then
  4. 该函数还将返回一个 ,以允许链接多个调用。thenpromise
  5. 每个处理程序(成功或错误)可以返回一个 ,它将作为 s 链中的下一个函数传递给下一个函数。valueargumentpromise
  6. 如果处理程序返回 (发出另一个异步请求),则只有在该请求完成后才会调用下一个处理程序(成功或错误)。promise

因此,前面的示例代码可能会转换为如下所示的内容,使用 promise 和服务(在 AngularJs 中):$http

$http.get('/api/server-config').then(
    function(configResponse) {
        return $http.get('/api/' + configResponse.data.USER_END_POINT);
    }
).then(
    function(userResponse) {
        return $http.get('/api/' + userResponse.data.id + '/items');
    }
).then(
    function(itemResponse) {
        // Display items here
    }, 
    function(error) {
        // Common error handling
    }
);

传播成功和错误

链接承诺是一种非常强大的技术,它允许我们完成许多功能,例如让服务调用服务器,对数据进行一些后处理,然后将处理后的数据返回到控制器。但是,当我们使用链条时,我们需要记住一些事情。promise

考虑以下假设链,其中包含三个承诺,P1,P2和P3。每个都有一个成功处理程序和一个错误处理程序,因此 S1 和 E1 用于 P1,S2 和 E2 用于 P2,S3 和 E3 用于 P3:promisepromise

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3

在正常流程中,如果没有错误,应用程序将流经 S1、S2,最后是 S3。但在现实生活中,事情从来都不是那么顺利。P1 可能会遇到错误,或者 P2 可能会遇到错误,从而触发 E1 或 E2。

请考虑以下情况:

• 我们从 P1 中的服务器收到成功的响应,但返回的数据不正确,或者服务器上没有可用的数据(想想空数组)。在这种情况下,对于下一个承诺 P2,它应该触发错误处理程序 E2。

• 我们收到承诺 P2 的错误,触发了 E2。但是在处理程序内部,我们有来自缓存的数据,确保应用程序可以正常加载。在这种情况下,我们可能希望确保在 E2 之后调用 S3。

因此,每次我们编写成功或错误处理程序时,我们都需要进行调用 - 给定我们当前的函数,对于承诺链中的下一个处理程序,这个承诺是成功还是失败?

如果我们想触发链中下一个承诺的成功处理程序,我们可以从成功或错误处理程序返回一个值

另一方面,如果我们想触发链中下一个承诺的错误处理程序,我们可以使用延迟对象并调用其inject()方法来做到这一点。

现在什么是延迟对象?

jQuery 中的延迟对象表示稍后(通常是异步)完成的工作单元。工作单元完成后,可以将对象设置为已解决或失败。deferred

对象包含对象。通过对象,您可以指定工作单元完成时要执行的操作。您可以通过在对象上设置回调函数来执行此操作。deferredpromisepromisepromise

Jquery 中的延迟对象:https://api.jquery.com/jquery.deferred/

AngularJs中的延迟对象:https://docs.angularjs.org/api/ng/service/$q


答案 2

then()函数与一些库或框架(如jQuery或AngularJS)中使用的“Javascript promises”有关。

承诺是处理异步操作的模式。promise 允许您调用一个名为“then”的方法,该方法允许您指定要用作回调的函数。

有关详细信息,请参阅: http://wildermuth.com/2013/8/3/JavaScript_Promises

对于Angular承诺:http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/