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

Kay*_*ale 244 javascript

我一直在看代码如下:

myObj.doSome("task").then(function(env) {
    // logic
});
Run Code Online (Sandbox Code Playgroud)

哪里then()来的?

Sid*_*Sid 293

在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
            });
        });
    });
Run Code Online (Sandbox Code Playgroud)

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

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

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

Promise API提出以下建议:

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

因此,前面的示例代码可能会使用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
    }
);
Run Code Online (Sandbox Code Playgroud)

传播成功与错误

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

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

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3
Run Code Online (Sandbox Code Playgroud)

在没有错误的正常流程中,应用程序将流经S1,S2,最后流经S3.但在现实生活中,事情从未如此顺利.P1可能会遇到错误,或P2可能会遇到错误,触发E1或E2.

考虑以下情况:

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

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

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

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

另一方面,如果我们想要触发链中下一个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

  • 写得很好。这帮助我真正确定了承诺。 (9认同)

小智 79

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/

  • 所以它就像一个在任务完成时执行的回调?它有什么不同 (4认同)
  • 另一条评论中的[JavaScript Promises](http://www.html5rocks.com/en/tutorials/es6/promises/)说:"承诺只能成功或失败一次",并且"如果承诺成功或者失败并且您稍后添加成功/失败回调,将调用正确的回调 (2认同)

use*_*716 31

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

似乎doSome("task")返回的任何东西都有一个叫做的方法then.

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

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

更新(截至ECMAScript6): -

.then()功能已包含在纯JavaScript中.

这里的Mozilla文档中,

then()方法返回一个Promise.它有两个参数:Promise的成功和失败案例的回调函数.

反过来,Promise对象被定义为

Promise对象用于延迟和异步计算.Promise表示尚未完成的操作,但预计将来会发生.

也就是说,Promise作为尚未计算的值的占位符,但将来会被解决.并且该.then()函数用于在解析时将要在Promise上调用的函数关联起来 - 无论是成功还是失败.

  • 当时没有内置的`.then`,但现在ES6中的本机承诺:http://www.html5rocks.com/en/tutorials/es6/promises/ (12认同)

Mag*_*nus 14

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

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>'
}
Run Code Online (Sandbox Code Playgroud)
<div id='msg'></div>
Run Code Online (Sandbox Code Playgroud)


NVR*_*VRM 7

{}这是关于我们的箭头函数中花括号的使用:


这 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!")
Run Code Online (Sandbox Code Playgroud)


使用箭头函数速记的相同逻辑,无需{}

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!")
Run Code Online (Sandbox Code Playgroud)


箭头函数与{}

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!")
Run Code Online (Sandbox Code Playgroud)


小智 7

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

好的例子是:

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

doSome.then(function(value){
    console.log(value);
});
Run Code Online (Sandbox Code Playgroud)

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


Tar*_*ngh 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 !!");});
Run Code Online (Sandbox Code Playgroud)

另一个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}`)
})
Run Code Online (Sandbox Code Playgroud)

Definition :: then是一个用于解决异步回调的方法

这是在ES6中引入的

请在此处找到Es6 Promises的相应文档


hvg*_*des 4

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

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

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

  • *我怀疑 doSome 返回这个* - 没有任何证据强制/证明这种怀疑 (2认同)