简体   繁体   English

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

[英]What does the function then() mean in JavaScript?

I've been seeing code that looks like:我一直在看到看起来像这样的代码:

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

Where does then() come from? then()从何而来?

The traditional way to deal with asynchronous calls in JavaScript has been with callbacks.在 JavaScript 中处理异步调用的传统方法是使用回调。 Say we had to make three calls to the server, one after the other, to set up our application.假设我们必须一个接一个地对服务器进行三个调用来设置我们的应用程序。 With callbacks, the code might look something like the following (assuming a xhrGET function to make the server call):使用回调,代码可能如下所示(假设使用 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
            });
        });
    });

In this example, we first fetch the server configuration.在此示例中,我们首先获取服务器配置。 Then based on that, we fetch information about the current user, and then finally get the list of items for the current user.然后基于此,我们获取有关当前用户的信息,然后最终获取当前用户的项目列表。 Each xhrGET call takes a callback function that is executed when the server responds.每个 xhrGET 调用都采用一个回调函数,该函数在服务器响应时执行。

Now of course the more levels of nesting we have, the harder the code is to read, debug, maintain, upgrade, and basically work with.当然,现在我们拥有的嵌套级别越多,代码就越难阅读、调试、维护、升级和基本使用。 This is generally known as callback hell.这通常被称为回调地狱。 Also, if we needed to handle errors, we need to possibly pass in another function to each xhrGET call to tell it what it needs to do in case of an error.此外,如果我们需要处理错误,我们可能需要将另一个函数传递给每个 xhrGET 调用,以告诉它在发生错误时需要做什么。 If we wanted to have just one common error handler, that is not possible.如果我们只想拥有一个通用的错误处理程序,那是不可能的。

The Promise API was designed to solve this nesting problem and the problem of error handling. Promise API 旨在解决这种嵌套问题和错误处理问题。

The Promise API proposes the following: Promise API 提出以下建议:

  1. Each asynchronous task will return a promise object.每个异步任务都会返回一个promise对象。
  2. Each promise object will have a then function that can take two arguments, a success handler and an error handler.每个promise对象都有一个then函数,该函数可以接受两个参数,一个success处理程序和一个error处理程序。
  3. The success or the error handler in the then function will be called only once , after the asynchronous task finishes. then函数中的成功错误处理程序只会在异步任务完成后调用一次
  4. The then function will also return a promise , to allow chaining multiple calls. then函数还将返回一个promise ,以允许链接多个调用。
  5. Each handler (success or error) can return a value , which will be passed to the next function as an argument , in the chain of promise s.每个处理程序(成功或错误)都可以返回一个value ,该值将作为argument传递给下一个函数,位于promise链中。
  6. If a handler returns a promise (makes another asynchronous request), then the next handler (success or error) will be called only after that request is finished.如果一个处理程序返回一个promise (发出另一个异步请求),那么只有在该请求完成后才会调用下一个处理程序(成功或错误)。

So the previous example code might translate to something like the following, using promises and the $http service(in AngularJs):因此,使用 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
    }
);

Propagating Success and Error传播成功和错误

Chaining promises is a very powerful technique that allows us to accomplish a lot of functionality, like having a service make a server call, do some postprocessing of the data, and then return the processed data to the controller.链接 Promise 是一种非常强大的技术,它允许我们完成很多功能,比如让服务调用服务器,对数据进行一些后处理,然后将处理后的数据返回给控制器。 But when we work with promise chains, there are a few things we need to keep in mind.但是当我们使用promise链时,我们需要记住一些事情。

Consider the following hypothetical promise chain with three promises, P1, P2, and P3.考虑以下具有三个承诺 P1、P2 和 P3 的假设promise链。 Each promise has a success handler and an error handler, so S1 and E1 for P1, S2 and E2 for P2, and S3 and E3 for P3:每个promise都有一个成功处理程序和一个错误处理程序,因此 P1 为 S1 和 E1,P2 为 S2 和 E2,P3 为 S3 和 E3:

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

In the normal flow of things, where there are no errors, the application would flow through S1, S2, and finally, S3.在没有错误的正常流程中,应用程序将流经 S1、S2,最后是 S3。 But in real life, things are never that smooth.但在现实生活中,事情从来没有那么顺利。 P1 might encounter an error, or P2 might encounter an error, triggering E1 or E2. P1 可能会遇到错误,或者 P2 可能会遇到错误,从而触发 E1 或 E2。

Consider the following cases:考虑以下情况:

• We receive a successful response from the server in P1, but the data returned is not correct, or there is no data available on the server (think empty array). • 我们在P1 中收到来自服务器的成功响应,但返回的数据不正确,或者服务器上没有可用数据(认为是空数组)。 In such a case, for the next promise P2, it should trigger the error handler E2.在这种情况下,对于下一个 Promise P2,它应该触发错误处理程序 E2。

• We receive an error for promise P2, triggering E2. • 我们收到promise P2 的错误,触发E2。 But inside the handler, we have data from the cache, ensuring that the application can load as normal.但是在处理程序内部,我们有来自缓存的数据,确保应用程序可以正常加载。 In that case, we might want to ensure that after E2, S3 is called.在这种情况下,我们可能希望确保在 E2 之后调用 S3。

So each time we write a success or an error handler, we need to make a call—given our current function, is this promise a success or a failure for the next handler in the promise chain?因此,每次我们编写成功或错误处理程序时,我们都需要进行调用——给定我们当前的函数,对于 Promise 链中的下一个处理程序,这个 Promise 是成功还是失败?

If we want to trigger the success handler for the next promise in the chain, we can just return a value from the success or the error handler如果我们想为链中的下一个 Promise 触发成功处理程序,我们可以从成功或错误处理程序中返回一个值

If, on the other hand, we want to trigger the error handler for the next promise in the chain, we can do that using a deferred object and calling its reject() method另一方面,如果我们想为链中的下一个 Promise 触发错误处理程序,我们可以使用deferred对象并调用其reject()方法来实现

Now What is deferred object?现在什么是延迟对象?

Deferred objects in jQuery represents a unit of work that will be completed later, typically asynchronously. jQuery 中的延迟对象表示稍后将完成的工作单元,通常是异步的。 Once the unit of work completes, the deferred object can be set to resolved or failed.工作单元完成后,可以将deferred对象设置为已解决或失败。

A deferred object contains a promise object. deferred对象包含一个promise对象。 Via the promise object you can specify what is to happen when the unit of work completes.通过promise对象,您可以指定工作单元完成时要发生的事情。 You do so by setting callback functions on the promise object.您可以通过在promise对象上设置回调函数来实现。

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

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

then() function is related to "Javascript promises" that are used in some libraries or frameworks like jQuery or AngularJS. then() 函数与一些库或框架(如 jQuery 或 AngularJS)中使用的“Javascript 承诺”有关。

A promise is a pattern for handling asynchronous operations. Promise 是一种处理异步操作的模式。 The promise allows you to call a method called "then" that lets you specify the function(s) to use as the callbacks.该承诺允许您调用一个名为“then”的方法,该方法允许您指定要用作回调的函数。

For more information see: http://wildermuth.com/2013/8/3/JavaScript_Promises有关更多信息,请参阅: http ://wildermuth.com/2013/8/3/JavaScript_Promises

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

To my knowledge, there isn't a built-in then() method in javascript (at the time of this writing).据我所知, javascript中没有内置的then()方法(在撰写本文时)。

It appears that whatever it is that doSome("task") is returning has a method called then .看来,无论doSome("task")返回的是什么,都有一个名为then的方法。

If you log the return result of doSome() to the console, you should be able to see the properties of what was returned.如果您将doSome()的返回结果记录到控制台,您应该能够看到返回内容的属性。

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

UPDATE (As of ECMAScript6) :-更新(从 ECMAScript6 开始) :-

The .then() function has been included to pure javascript. .then()函数已包含在纯 JavaScript 中。

From the Mozilla documentation here ,这里的 Mozilla 文档中,

The then() method returns a Promise. then() 方法返回一个 Promise。 It takes two arguments: callback functions for the success and failure cases of the Promise.它有两个参数:Promise 成功和失败情况的回调函数。

The Promise object, in turn, is defined as反过来,Promise 对象被定义为

The Promise object is used for deferred and asynchronous computations. Promise 对象用于延迟和异步计算。 A Promise represents an operation that hasn't completed yet, but is expected in the future. Promise 表示尚未完成但预计会在未来完成的操作。

That is, the Promise acts as a placeholder for a value that is not yet computed, but shall be resolved in the future.也就是说, Promise充当尚未计算但将在未来解决的值的占位符。 And the .then() function is used to associate the functions to be invoked on the Promise when it is resolved - either as a success or a failure. .then()函数用于关联 Promise 解决时要调用的函数 - 无论是成功还是失败。

Here is a thing I made for myself to clear out how things work.这是我为自己做的一件事,目的是弄清楚事情是如何运作的。 I guess others too can find this concrete example useful:我想其他人也会发现这个具体的例子很有用:

 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>

It's about the use of curly braces {} in our arrow functions:这是关于在我们的箭头函数中使用花括号{}


Those 3 examples are doing the same thing (nothing, but have valid grammar , and are a valid Promise chain! )这 3 个示例在做同样的事情(什么都没有,但有有效的语法,并且是有效的 Promise 链!


 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, ..) */ }) console.log("This code has no errors GG!")


The same logic using arrow functions shorthand without {}使用没有{}的箭头函数速记的相同逻辑

 new Promise((ok) => ok( /* myFunc1(param1, param2, ..) */ ).then(() => 0 // HEY DID YOU NOTICE! A number that does nothing, // but otherwise the parsing will fail! // The code is pretty clean but have a major downside // As arrow functions without {} can contains only one declaration // console.log("something") will FAIL here ).then(() => "" // HEY DID YOU NOTICE! An empty string that does nothing, // but otherwise the parsing will fail! // As arrow functions without {} can contains only one declaration // We can't add more code here, hence: // console.log("something") // Will break the whole promise // This is likely the error in y(our) code ;) )) console.log("This code has no errors GG!")


Arrow function with {}带有{}的箭头函数

 new Promise( (ok) => { ok( /* myFunc1(param1, param2, ..) */ ) }).then( () => { /* myFunc1 succeed */ /* Launch something else */ }).then( () => { /* myFunc2 succeed */ /* Launch something else */ /* myFunc3(whatever38, ..) */ console.log("something") /* More console logs! */ console.log("something else") }) console.log("This code has no errors GG!")

.then returns a promise in async function. .then在异步函数中返回一个承诺。

Good Example would be:很好的例子是:

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

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

To add another logic to it, you can also add the reject('I am the rejected param') call the function and console.log it.要为其添加另一个逻辑,您还可以添加reject('I am the rejected param')调用该函数并 console.log 它。

Here is a small JS_Fiddle.这是一个小的JS_Fiddle。

then is a method callback stack which is available after a promise is resolved it is part of library like jQuery but now it is available in native JavaScript and below is the detail explanation how it works then是一个方法回调堆栈,在 promise 解决后可用

You can do a Promise in native JavaScript : just like there are promises in jQuery, Every promise can be stacked and then can be called with Resolve and Reject callbacks, This is how you can chain asynchronous calls.您可以在原生 JavaScript 中执行 Promise:就像 jQuery 中的 Promise 一样,每个 Promise 都可以堆叠,然后可以使用 Resolve 和 Reject 回调进行调用,这就是您可以链接异步调用的方式。

I forked and Edited from MSDN Docs on Battery charging status..我从关于电池充电状态的 MSDN Docs 分叉和编辑..

What this does is try to find out if user laptop or device is charging battery.这样做是试图找出用户笔记本电脑或设备是否正在为电池充电。 then is called and you can do your work post success.然后被调用,您可以在成功后完成您的工作。

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

Another es6 Example另一个 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}`)
})

Definition :: then is a method used to solve Asynchronous callbacks定义:: then是一种用于解决异步回调的方法

this is introduced in ES6这是在ES6中引入的

Please find the proper documentation here Es6 Promises请在此处找到正确的文档Es6 Promises

I suspect doSome returns this, which is myObj, which also has a then method.我怀疑 doSome 返回这个,即 myObj,它也有一个 then 方法。 Standard method chaining...标准方法链...

if doSome is not returning this, being the object on which doSome was executed, rest assured it is returning some object with a then method...如果 doSome 没有返回这个,作为执行 doSome 的对象,请放心,它正在使用 then 方法返回一些对象......

as @patrick points out, there is no then() for standard js正如@patrick 指出的那样,标准 js 没有 then()

doSome("task")must be returning a promise object , and that promise always have a then function .So your code is just like this doSome("task") 必须返回一个 promise 对象,并且该 promise 总是有一个 then 函数。所以你的代码就是这样

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

and you know this is just an ordinary call to member function .你知道这只是对成员函数的普通调用。

The ".then()" function is wideley used for promised objects in Asynchoronus programming For Windows 8 Store Apps. “.then()”函数广泛用于 Asynchoronus 编程中的承诺对象,用于 Windows 8 商店应用程序。 As far as i understood it works some way like a callback.据我了解,它的工作方式类似于回调。

Find Details in this Documentantion http://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx在本文档中查找详细信息http://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx

Of Cause it could also be the name for any other defined function.当然,它也可以是任何其他已定义函数的名称。

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

I am about 8 years late, well...anyways, I don't really know what then() does but maybe MDN might have an answer.我迟到了大约 8 年,嗯......无论如何,我真的不知道 then() 做了什么,但也许 MDN 可能会有答案。 Actually, I might actually understand it a little more.其实,我可能会更了解它。

This will show you all the information (hopefully), you need.这将向您显示您需要的所有信息(希望如此)。 Unless someone already posted this link.除非有人已经发布了这个链接。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

The format is promise.prototype.then() The promise and prototype are kind of like variables but not like variables in javascript, I mean like other things go there like navigator.getBattery().then() where this one actually exists but is barely used on the web, this one shows statuses about the battery of the device, more information and more on MDN if you are curious.格式是 promise.prototype.then() 承诺和原型有点像变量,但不像 javascript 中的变量,我的意思是像其他东西一样去那里,比如 navigator.getBattery().then() 实际存在但几乎没有在网络上使用过,如果您好奇的话,它会显示有关设备电池的状态、更多信息和 MDN 上的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM