JS中的Promise的ajax then方法法做了啥

NodeJS的Promise的用法
& & & &&& & &
 Javascript的特点是异步,Javascript不能等待,如果你实现某件需要等待的事情,你不能停在那里一直等待结果回来,相反,底线是使用回调callback:你定义一个函数,这个函数只有等到结果可用时才能被调用。
 这种回调模型对于好的代码组织是没有问题的,但是也可以通过从原始回调切换到promise解决很多问题,将promise看成是一个标准的数据容器,这样会简化你的代码组织,可以成为基于promise的架构。
什么是Promise?
 一个promise是一个带有&.then()&方法的对象,其代表的是一个操作的结果可能还没有或不知道,无论谁访问这个对象,都能够使用&.then()&方法加入回调等待操作出现成功结果或失败时的提醒通知,。
 那么为什么这样做好处优于回调呢?标准的回调模式在我们处理请求时需要同时提供回调函数:
request(url, function(error, response)
handle success or error.
doSomethingElse();
 很不幸,这段代码意味着这个request函数并不知道它自己什么时候能够完成,当然也没有必要,我们最终通过回调传递结果。这会导致多个回调形成了嵌套回调,或者称为回调陷阱。
queryTheDatabase(query, function(error,
request(url, function(error, response) {
doSomethingElse(response, function(error, result) {
doAnotherThing(result, function(error, result) {
request(anotherUrl, function(error, response) {
 Promise能够解决这种问题,允许低层代码创建一个request然后返回一个对象,其代表着未完成的操作,让调用者去决定应该加入什么回调。
Promise是什么?
 promise是一个异步编程的抽象,它是一个返回值或抛出exception的代理对象,一般promise对象都有一个then方法,这个then方法是我们如何获得返回值(成功实现承诺的结果值,称为fulfillment)或抛出exception(拒绝承诺的理由,称为rejection),then是用两个可选的回调作为参数,我们可以称为onFulfilled和OnRejected:
var promise = doSomethingAync()
promise.then(onFulfilled, onRejected)
 当这个promise被解决了,也就是异步过程完成后,onFulfilled和OnRejected中任何一个将被调用,
 因此,一个promise有下面三个不同状态:
pending待承诺 - promise初始状态
fulfilled实现承诺 - 一个承诺成功实现状态
rejected拒绝承诺 - 一个承诺失败的状态
 以读取文件为案例,下面是使用回调实现读取文件后应该做什么事情(输出打印):
readFile(function (err, data) {
(err) return console.error(err)
console.log(data)
 如果我们的readFile函数返回一个promise,那么我们可以如下实现同样的逻辑(输出打印):
var promise = readFile()
promise.then(console.log, console.error)
 这里我们有了一个值promise代表的是异步操作,我们能够一直传递这个值promise,任何人访问这个值都能够使用then来消费使用它,无论这个值代表的异步操作是否完成或没有完成,我们也能保证异步的结果不会改变,因为这个promise代表的异步操作只会执行一次,状态是要么fulfilled要么是rejected。
理解Promise
 Promise可能是不同于日常直觉,为了理解它,一些重要原理必须记牢: .then()总是返回一个新的promise.,如下面代码:
var promise = readFile()
var promise2 = promise.then(readAnotherFile, console.error)
 这里then的参数readAnotherFile, console.error是代表异步操作成功后的动作onFulfilled或失败后的动作OnRejected,也就是说,读取文件成功后执行readAnotherFile函数,否则失败打印记录错误。这种实现是两个中只有一种可能。
 我们再看下面上述代码如下:
var promise = readFile()
var promise2 = promise.then(function (data)
return readAnotherFile() // 如果readFile成功,执行readAnotherFile
}, function (err) {
console.error(err) // 如果readFile不成功,记录,但是还是执行readAnotherFile
return readAnotherFile()
promise2.then(console.log, console.error)
// readAnotherFile函数的执行结果
 因为then返回一个promise,它意味着promise能够被chain串行链条花,这样能避免回调地狱:
readFile()
.then(readAnotherFile)
.then(doSomethingElse)
.then(...)
 Promise法则有两部分必须分离:
 (1).then()总是返回一个新的promise,每次你调用它,它不管回调做什么,因为.then()在回调被调用之前已经给了你一个承诺promise,回调的行为只影响承诺promise的实施,如果回调返回一个值,那么promise将使用那个值,如果这个值是一个promise,返回这个promise实施后的值给这个值,如果回调抛出错误,promise将拒绝错误。
 (2)被.then()返回的promise是一个新的promise,它不同于那些.then()被调用的promise,promise长长的链条有时会好些隐藏这个事实,不管如何,每次.then()调用都会产生一个新的promise,这里必须注意的是你真正需要考虑的是你最后调用.then()可能代表失败,那么如果你不捕获这种失败,那么容易导致你的错误exception消失。
 一些人认为.then()串联链条调用很类似fluent风格,但是长长的promise链条会让人迷惑,最后切分为一个个有意义的函数:
function getTasks() {
return $http.get('/api/v1/tasks')
.then(function(response) {
return response.
function getMyTasks() {
return getTasks()
.then(function(tasks) {
return filterTasks(tasks, {
owner: user.username
 在这个例子中,两个函数各自获得一个promise,携带了一个回调函数。
有趣的Promise
 同样的promise能够接受任何数目的回调,当一个Promise被解决实施后,其中所有回调函数都会被调用,此外,一个promise在被解决实施后,甚至可以接受一个新的回调,这些回调完成能以正常方式被调用,这就允许我们使用回调实现简单形式的缓存:
var tasksP
function getTasks() {
taskPromise = taskPromise || getTasksFromTheServer();
return taskP
 这个案例中,getTasks()函数可以被任意次数调用,它总是返回铜牙的promise,其中函数getTasksFromTheServer()却只是被调用一次。
| 网站地图 | 设为首页nodejs异步控制「co、async、Q 、『es6原生promise』、then.js、bluebird」有何优缺点?最爱哪个?哪个简单? - 知乎1100被浏览126101分享邀请回答npmjs.org/package/shell-taskCallback-based 方案的最大问题在于异常处理,每个 callback 都得额外接受一个异常参数,发生异常就得一个一个往后传,异常发生后的定位很麻烦。ES6 Promise, Q, Bluebird 核心都是 Promise,缺点嘛就是必须引入这个新概念并且要用就得所有的地方都用 Promise。对于 Node 的原生 API,需要进行二次封装。Q 和 Bluebird 都是在实现 Promise A+ 标准的基础上提供了一些封装和帮助方法,比如 Promise.map 来进行并行操作等等。Promise 的一个问题就是性能,而 Bluebird 号称速度是所有 Promise 库里最快的。ES6 Promise 则是把 Promise 的包括进 js 标准库里,这样你就不需要依赖第三方实现了。关于 Promise 能够如何改进异步流程,建议阅读:co 是 TJ 大神基于 ES6 generator 的异步解决方案。要理解 co 你得先理解 ES6 generator,这里就不赘述了。co 最大的好处就是能让你把异步的代码流程用同步的方式写出来,并且可以用 try/catch:co(function *(){
var res = yield get('http://badhost.invalid');
console.log(res);
} catch(e) {
console.log(e.code) // ENOTFOUND
但用 co 的一个代价是 yield 后面的函数必须返回一个 Thunk 或者一个 Promise,对于现有的 API 也得进行一定程度的二次封装。另外,由于 ES6 generator 的支持情况,并不是所以地方都能用。想用的话有两个选择:1. 用支持 ES6 generator 的引擎。比如 Node 0.11+ 开启 --harmony flag,或者直接上2. 用预编译器。比如 Babel () , Traceur () 或是 Regenerator () 把带有 generator 的 ES6 代码编译成 ES5 代码。(延伸阅读:基于 ES6 generator 还可以模拟 go 风格的、基于 channel 的异步协作:)但是 generator 的本意毕竟是为了可以在循环过程中 yield 进程的控制权,用 yield 来表示 “等待异步返回的值” 始终不太直观。因此 ES7 中可能会包含类似 C# 的 async/await :async function showStuff () {
var data = await loadData() // loadData 返回一个 Promise
console.log(data) // data 已经加载完毕
async function () {
await showStuff() // async 函数默认返回一个 Promise, 所以可以 await 另一个 async 函数
// 这里 showStuff 已经执行完毕
可以看到,和用 co 写出来的代码很像,但语意上更清晰。因为本质上 ES7 async/await 就是基于 Promise + generator 的一套语法糖。深入阅读:想要今天就用 ES7 async/await 也是可以的!Babel 的话可以用配套的 asyncToGenerator transform: Traceur 和 Regenerator 对其也已经有实验性的支持了。另外,Fiber 其实也是一个不错的抽象,只可惜和 ES 目前的发展不一致,不太可能应用到浏览器端。Fiber 和 async/await 的相似处在于程序逻辑可以用接近同步的方式表现,但应用了 Fiber 之后异步和同步的方法调用是看不出区别的。Meteor 框架内部就大量应用了 Fiber。---2015 年 10 月更新:- async/await 已经升级为 stage 3 proposal,纳入正式规范指日可待- Microsoft Edge 已经率先原生支持 async/await:28915 条评论分享收藏感谢收起在 SegmentFault,解决技术问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
一线的工程师、著名开源项目的作者们,都在这里:
获取验证码
已有账号?
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
楼主下去看了下, 这是Promise实现所要遵循的标准, 看了之后模拟了一份, 目前已经打包好放在上。弄懂promise不容易啊。发出来大家学习啦~
export default class Promise {
// internal method
resolvePromise(y) {
if (this.status === 'pending') {
this.status = 'fulfilled'
this.value = y
if (Array.isArray(this.nextPromises)) {
this.nextPromises.forEach((nextPromise, index) =& {
const onFulfilled = this.onFulfilleds[index]
if (typeof onFulfilled === 'function') {
const y = onFulfilled(y)
Promise.Resolve(nextPromise, this.value)
this.onFulfilleds[index] = null
// internal method
rejectPromise(r) {
if (this.status === 'pending') {
this.status = 'rejected'
this.result = r
if (Array.isArray(this.nextPromises)) {
this.nextPromises.forEach((nextPromise, index) =& {
const onRejected = this.onRejecteds[index]
if (typeof onRejected === 'function') {
const x = onRejected(r)
Promise.Resolve(nextPromise, this.result)
this.onRejecteds[index] = null
// internal method
static Resolve(nextPromise, x) {
if (nextPromise === x) { throw new TypeError() }
if (x instanceof Promise) {
x.then(nextPromise.resolvePromise, nextPromise.rejectPromise)
if (typeof x === 'object' || typeof x === 'function') {
const then = x.then
if (typeof then === 'function') {
const resolvePromise = nextPromise.resolvePromise.bind(nextPromise)
const rejectPromise = nextPromise.rejectPromise.bind(nextPromise)
then.call(x, resolvePromise, rejectPromise)
} catch (e) {
nextPromise.rejectPromise(e)
nextPromise.resolvePromise(x)
nextPromise.resolvePromise(x)
constructor(executor) {
this.status = 'pending'
const resolvePromise = this.resolvePromise.bind(this)
const rejectPromise
= this.rejectPromise.bind(this)
executor(resolvePromise, rejectPromise)
then(onFulfilled, onRejected) {
const nextPromise = new Promise((resolve, reject) =& {
setTimeout(() =& {
if (this.status === 'fulfilled') {
const x = onFulfilled(this.value)
Promise.Resolve(nextPromise, x)
} else if (this.status === 'rejected') {
const x = onRejected(this.result)
Promise.Resolve(nextPromise, x)
this.onFulfilleds = this.onFulfilleds || []
this.onRejecteds
= this.onRejecteds
this.nextPromises = this.nextPromises || []
const length = this.nextPromises.length
(typeof onFulfilled === 'function') && (this.onFulfilleds[length] = onFulfilled)
(typeof onRejected === 'function')
&& (this.onRejecteds[length]
= onRejected)
this.nextPromises.push(nextPromise)
return nextPromise
--------------------------之前的东东
Promise.resolve(1).then(arg =& {
return new Promise(arg)
}).then(arg =& console.log(arg))
这串代码没有任何输出结果,问了下gitter,说原因是new Promise(arg)是一个状态为Pending的promise对象, 会在这条链上卡主, 不会往下执行. 这让我感到有点困惑, 赶紧去翻了下MDN.MDN是这样描述then方法的.
the then method returns a Promise, you can easily chain then calls. Values returned from the onFulfilled or onRejected callback functions will be automatically wrapped in a resolved promise.
看了MDN的描述,百思不得其解. 对Promise的内部原理甚为困惑. 一个promise对象(状态是fulfilled)调用then的时候会生成一个promise对象, 这个promise对象是pending的, 会异步执行then方法的第一个回调方法, 然后Promise内部是如何包装then方法的返回值的呢?
楼主有一个假设, 用代码描述出来, 不知道是否正确....
function then(resolveHandler, rejectHandler) {
const newPromise = new Promise((resolve, reject) =& {
setTimeout(() =& {
// 如果调用then方法的promise的status是rejected
if(this.status === 'rejected') {
rejectHandler(this.result)
// 不是rejected 就是fulfilled
const returnValue = resolveHandler()
// 如果returnValue不是promise类型的话
if (returnValue.___proto__ !== Promise) {
wrapPromise = Promise.resolve(returnValue)
//包装返回值
wrapPromise.then(resolve)
returnValue.then(resolve, reject)
return newPromise
楼主想了之后觉得then是这样的. 大神们给出新姿势~
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
最适合学习Promise+规范的Promise实现:
非常短、很清晰、很容易理解,强烈建议结合规范通读。
该答案已被忽略,原因:不符合问题要求
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:

我要回帖

更多关于 js中的then方法 的文章

 

随机推荐