mingyunyuziyou

then()和Promise的使用

作者: 秒速五厘米     
 


then()方法是异步执行

就是当.then()前的方法执行完后再执行then()内部的程序
这样就避免了,数据没获取到等的问题


then 方法(承诺)
允许你指定实现承诺时要完成的工作。

语法

promise.then(onCompleted, onRejected);

参数

  • promise
    必需。
    Promise 对象。

  • onCompleted
    必需。
    承诺成功完成时要运行的履行处理程序函数。

  • onRejected
    可选。
    承诺被拒绝时要运行的错误处理程序函数。


备注
承诺必须完成(返回一个值)或者必须被拒绝(返回一个原因)。承诺完成或被拒绝时(无论哪一个先发生),Promise 对象的 then 方法都会运行。

如果承诺成功完成,则将运行 then 方法的履行处理程序函数。如果承诺被拒绝,则将运行 then 方法(或 catch 方法)的错误处理程序函数。


下面的示例演示如何调用返回承诺的函数 (timeout)。
达到 5000 ms 的超时时间后,将运行 then 方法的履行处理程序。

function timeout(duration) { 
  return new Promise(function(resolve, reject) { 
    setTimeout(resolve, duration); 
  });
}

// Note: This code uses arrow function syntax
var m = timeout(5000).then(() => { 
  console.log("done!");
})

// Output (after 5 seconds):
// done!


如果还有疑问再看一下Promise

“Promises” 代表着在javascript程序里下一个伟大的范式,但是理解他们为什么如此伟大不是件简单的事。它的核心就是一个promise代表一个任务结果,这个任务有可能完成有可能没完成。Promise模式唯一需要的一个接口是调用then方法,它可以用来注册当promise完成或者失败时调用的回调函数,这在CommonJS Promises/A proposal.大体讲到了。比如,我想保存一个Prase.Object对象,这是个异步操作,在旧的回调范式中,你的代码可能这样写:


object.save({ key: value }, {
  success:function(object) {
    // the object was saved.
  },
  error:function(object, error) {
    // saving the object failed.
  }
});


在新的Promise范式中,同样的代码你可以这样写:

object.save({ key: value }).then(
  function(object) {
   // the object was saved.
  },
 function(error) {
   // saving the object failed.
 });


没有多大的区别?那么有啥大不了的地方呢?好吧,promises的真正强大之处在于多重的链接,当调用promise.then(func)时返回一个新的promise,它不会执行直到上一个完成。但是这里有一种特殊的情况,如果我的回调通过then返回一个新的promise,那么通过then返回的promise将不会执行,直到回调执行完成。详细细节请参考 Promises/A+,这是个复杂的规则,通过例子我们能更清楚的认识下.


假设你写了段登陆的代码,查找对象然后更新它。在旧的回调范式中,你可以使用金字塔式的代码完成:

Parse.User.logIn("user","pass", {
 success:function(user) {
  query.find({
   success:function(results) {
    results[0].save({ key: value }, {
     success:function(result) {
      // the object was saved.
     }
    });
   }
  });
 }
});


这看起来已经很可笑,更可笑的是甚至没有任何错误处理。但是promise链式的结构,使代码看起来更舒服了:、

aParse.User.logIn("user","pass").then(function(user) {
 returnquery.find();
}).then(function(results) {
 returnresults[0].save({ key: value });
}).then(function(result) {
 // the object was saved.
});


哇!好多啦!

错误处理
上面的代码简单期间没有添加错误处理,但是添加了后你会发现在旧的回调代码中一团糟:

Parse.User.logIn("user","pass", {
 success:function(user) {
  query.find({
   success:function(results) {
    results[0].save({ key: value }, {
     success:function(result) {
      // the object was saved.
     },
     error:function(result, error) {
      // An error occurred.
     }
    });
   },
   error:function(error) {
    // An error occurred.
   }
  });
 },
 error:function(user, error) {
  // An error occurred.
 }
});


由于promises知道处理是否完成,它可以传递错误,不执行任何回调直到遇到错误。比如,上面的代码可以简写为:


Parse.User.logIn("user","pass").then(function(user) {
 returnquery.find();
}).then(function(results) {
 returnresults[0].save({ key: value });
}).then(function(result) {
 // the object was saved.
},function(error) {
 // there was some error.
});


通常,开发者认为一个异步的promise失败等同于抛出一个异常。事实上,如果一个回调抛出一个错误,promise将返回失败信息。把错误传递到下一个可用的错误处理器等同于抛出一次异常直到捕获处理。



aromises/A规范

<small>注:为了便于理解,描述可能和Promises/A规范有所出入;

 CommonJS之Promises/A规范,通过规范API接口来简化异步编程,使我们的异步逻辑代码更易理解。遵循Promises/A规范的实现我们称之为Promise对象,Promise对象有且仅有三种状态:unfulfilled(未完成)、fulfilled(已完成)、failed(失败/拒绝);初始创建的时候是unfulfilled(未完成)状态,状态只可以从unfulfilled(未完成)变成fulfilled(已完成),或者unfulfilled(未完成)变成failed(失败/拒绝)。状态一旦变成fulfilled(已完成)或者failed(失败/拒绝),状态就不能再变了。

Promises/A规范提供了一个在程序中描述延时(或将来)概念的解决方案。主要的思想不是执行一个方法然后阻塞应用程序等待结果返回后再回调其他方法,而是返回一个Promise对象来满足未来监听。fulfilled状态和failed状态都可以被监听。Promise通过实现一个then接口来返回Promise对象来注册回调:

复制代码代码如下:

then(fulfilledHandler, errorHandler, progressHandler);

then接口用于监听一个Promise的不同状态。fulfilledHandler用于监听fulfilled(已完成)状态,errorHandler用于监听failed(失败/拒绝)状态,progressHandler用于监听unfulfilled(未完成)状态。Promise不强制实现unfulfilled(未完成)的事件监听(例如我们知道旧版本的jQuery(1.5,1.6)的Deferred就是一个Promise的实现,但没有实现对unfulfilled(未完成)状态的监听来回调progressHandler)。

一般认为,then接口返回的是一个新的Promise对象,而不是原来的Promise对象,这个新的新的Promise对象可以理解为是原来Promise对象的一个视图,它只包含原有Promise对象的一组方法,这些方法只能观察原有Promise对象的状态,而无法更改deferred对象的内在状态。这样可以避免多个调用者之间的冲突,多个调用者可以通过改变新的Promise对象状态而不影响别的调用者。

另外,Promise提供了resolve(实现状态由未完成到已完成)和reject(实现状态由未完成到拒绝或失败)两个接口实现状态的转变。</small>

发一张图片帮助理解一下: