函数then()在JavaScript中意味着什么?

时间:2010-10-07 17:38:30

标签: javascript

我一直看到的代码如下:

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

then()来自哪里?

12 个答案:

答案 0 :(得分:249)

在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. 每个promise对象都有一个then函数,可以带两个参数,success 处理程序和error处理程序。
  3. 成功 then函数中的错误处理程序仅在一次后被调用 异步任务完成。
  4. then函数还会返回promise,以允许链接多个来电。
  5. 每个处理程序(成功或错误)都可以返回value,它将传递给下一个。{1}} 在argument s。
  6. 的链中起promise的作用
  7. 如果处理程序返回promise(发出另一个异步请求),那么下一个 只有在请求完成后才会调用handler(成功或错误)。
  8. 因此,前面的示例代码可能会转换为类似以下的内容,使用 promises和$http服务(在AngularJs中):

    $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链,我们需要记住一些事情。

    考虑以下具有三个承诺的假设promise链,P1,P2和P3。 每个promise都有一个成功处理程序和一个错误处理程序,所以S1和E1用于P1,S2和 P2为P2,S3为S3和E3:

    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。

    因此,每次我们编写成功或错误处理程序时,我们都需要拨打电话给我们 当前函数,这个承诺是promise中下一个处理程序的成功或失败 链

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

    另一方面,如果我们想要触发下一个承诺的错误处理程序 链,我们可以使用deferred对象并调用其reject()方法

      

    现在什么是延期对象?

         

    jQuery中的延迟对象代表了一个工作单元   稍后完成,通常是异步的。一旦工作单位   完成后,deferred对象可以设置为已解决或失败。

         

    deferred对象包含promise个对象。通过promise对象   您可以指定工作单元完成时要发生的事情。您   通过在promise对象上设置回调函数来实现此目的。

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

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

答案 1 :(得分:78)

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

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

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

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

答案 2 :(得分:29)

据我所知,then()中没有内置的javascript方法(在撰写本文时)。

doSome("task")返回的内容似乎有一个名为then的方法。

如果您将doSome()的返回结果记录到控制台,您应该能够看到返回内容的属性。

console.log( myObj.doSome("task") ); // Expand the returned object in the
                                     //   console to see its properties.

更新(自ECMAScript6起): -

纯{javascript}中包含.then()函数。

来自Mozilla文档here

  

then()方法返回一个Promise。它需要两个参数:回调   承诺的成功和失败案例的功能。

反过来,Promise对象被定义为

  

Promise对象用于延迟和异步   计算。 Promise表示尚未完成的操作   但是,预计在未来。

也就是说,Promise充当尚未计算的值的占位符,但将来会被解析。 .then()函数用于关联Promise在Promise上调用的函数 - 无论是成功还是失败。

答案 3 :(得分:12)

这是我为自己做的事情,以清除事情是如何运作的。我猜其他人也可以找到这个具体的例子:

doit().then(function() { log('Now finally done!') });
log('---- But notice where this ends up!');

// For pedagogical reasons I originally wrote the following doit()-function so that 
// it was clear that it is a promise. That way wasn't really a normal way to do 
// it though, and therefore Slikts edited my answer. I therefore now want to remind 
// you here that the return value of the following function is a promise, because 
// it is an async function (every async function returns a promise). 
async function doit() {
  log('Calling someTimeConsumingThing');
  await someTimeConsumingThing();
  log('Ready with someTimeConsumingThing');
}

function someTimeConsumingThing() {
  return new Promise(function(resolve,reject) {
    setTimeout(resolve, 2000);
  })
}

function log(txt) {
  document.getElementById('msg').innerHTML += txt + '<br>'
}
<div id='msg'></div>

答案 4 :(得分:5)

我怀疑doSome会返回这个,这是myObj,它也有一个then方法。标准方法链接......

如果doSome没有返回这个,作为执行doSome的对象,请放心,它会使用then方法返回一些对象......

正如@patrick指出的那样,标准js没有then()

答案 5 :(得分:5)

这是一个小JS_Fiddle.

然后是一个方法回调堆栈,它在解析了promise之后可用,它像jQuery一样是库的一部分,但现在它在本机JavaScript中可用,下面是详细解释它是如何工作的

你可以在本机JavaScript中做一个Promise:就像在jQuery中有promises一样,每个promise都可以堆叠,然后可以使用Resolve和Reject回调来调用,这就是你可以链接异步调用的方法。

我在电池充电状态下从MSDN Docs分叉编辑。

这样做是为了确定用户笔记本电脑或设备是否正在为电池充电。然后被叫,你可以在成功后做你的工作。

navigator
    .getBattery()
    .then(function(battery) {
       var charging = battery.charging;
       alert(charging);
    })
    .then(function(){alert("YeoMan : SINGH is King !!");});

另一个es6示例

function fetchAsync (url, timeout, onData, onError) {
    …
}
let fetchPromised = (url, timeout) => {
    return new Promise((resolve, reject) => {
        fetchAsync(url, timeout, resolve, reject)
    })
}
Promise.all([
    fetchPromised("http://backend/foo.txt", 500),
    fetchPromised("http://backend/bar.txt", 500),
    fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
    let [ foo, bar, baz ] = data
    console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
    console.log(`error: ${err}`)
})
  

定义:: 然后是用于解决异步回调的方法

     

这是在 ES6

中引入的      

请在Es6 Promises

找到相应的文档

答案 6 :(得分:1)

“.then()”函数广泛用于Asynchoronus编程中的承诺对象适用于Windows 8商店应用程序。 据我所知,它的工作方式就像回调一样。

在此Documentantion中查找详细信息 http://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx

原因它也可能是任何其他已定义函数的名称。

答案 7 :(得分:1)

doSome(“task”)必须返回一个promise对象,并且该promise总是有一个then函数。所以你的代码就像这样

promise.then(function(env) {
    // logic
}); 

你知道这只是对成员函数的普通调用。

答案 8 :(得分:0)

在这种情况下,then()doSome()方法返回的对象的类方法。

答案 9 :(得分:0)

我迟到了8年,好吧...无论如何,我真的不知道then()会做什么,但也许MDN可能有答案。实际上,我可能实际上对它有所了解。

这将向您显示所有需要的信息(希望如此)。除非有人已经发布了此链接。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

格式为promise.prototype.then() Promise和Prototype有点像变量,而不像javascript中的变量,我的意思是像其他东西一样,比如navigator.getBattery()。then(),尽管它实际上存在但很少在网络上使用,但它显示了状态有关设备电池的信息,如果您好奇的话,还可以获取有关MDN的更多信息和更多信息。

答案 10 :(得分:0)

另一个例子:

new Promise(function(ok) {
   ok( 
      /* myFunc1(param1, param2, ..) */
   )
}).then(function(){
     /* myFunc1 succeed */
     /* Launch something else */
     /* console.log(whateverparam1) */
     /* myFunc2(whateverparam1, otherparam, ..) */
}).then(function(){
     /* myFunc2 succeed */
     /* Launch something else */
     /* myFunc3(whatever38, ..) */
})

使用箭头功能速记的相同逻辑:

new Promise((ok) =>
   ok( 
      /* myFunc1(param1, param2, ..) */
)).then(() =>
     /* myFunc1 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc2(whateverparam1, otherparam, ..) */
).then(() =>
     /* myFunc2 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc3(whatever38, ..) */
)

答案 11 :(得分:0)

.then在异步函数中返回一个Promise。

很好的例子是:

var doSome = new Promise(function(resolve, reject){
    resolve('I am doing something');
});

doSome.then(function(value){
    console.log(value);
});

要向其中添加其他逻辑,您还可以添加reject('I am the rejected param')调用该函数并进行console.log记录。