如何把return回调函数返回值的返回值promise化

使用Promise模式来简化JavaScript的异步回调
网页的交互越来越复杂,JavaScript 的异步操作也随之越来越多。如常见的 ajax 请求,需要在请求完成时响应操作,请求通常是异步的,请求的过程中用户还能进行其他的操作,不会对页面进行阻塞,这种异步的交互效果对用户来说是挺有友好的。但是对于开发者来说,要大量处理这种操作,就很不友好了。异步请求完成的操作必须预先定义在回调函数中,等到请求完成就必须调用这个函数。这种非线性的异步编程方式会让开发者很不适应,同时也带来了诸多的不便,增加了代码的耦合度和复杂性,代码的组织上也会很不优雅,大大降低了代码的可维护性。情况再复杂点,如果一个操作要等到多个异步 ajax 请求的完成才能进行,就会出现回调函数嵌套的情况,如果需要嵌套好几层,那你就只能自求多福了。
先看看下面这个常见的异步函数。
var showMsg = function(){
setTimeout(function(){
alert( &hello& );
}, 5000 );
如果要给该函数添加回调,通常会这么干。
var showMsg = function( callback ){
setTimeout(function(){
alert( &hello& );
// 此处添加回调
callback();
}, 5000 );
如果是使用 easy.js 的 Promise,添加回调的方法就会优雅多了,前提是需要将原函数封装成一个 promise 实例。
var showMsg = function(){
// 构造promise实例
var promise = new E.Promise();
setTimeout(function(){
alert( &hello& );
// 改变promise的状态
promise.resolve( &done& );
}, 5000 );
// 返回promise实例
将一个普通的函数封装成一个 promise 实例,有3个关键步骤,第一步是在函数内部构造一个 promise 实例,第二步是部署函数执行完去改变 promise 的状态为已完成,第三步就是返回这个 promise 实例。每个 promise 实例都有3种状态,分别为 pending(未完成)、resolved(已完成,成功)、rejected(已拒绝,失败)。下面再来看看如何添加回调。
showMsg().then(function( str ){
// 回调添加到这里来了
callback( str );
这样就将回调函数和原来的异步函数彻底的分离了,从代码组织上看,优雅了很多。resolve 接受一个参数,该参数就可以轻松实现将数据传送给使用 then 方法添加的回调中。
对于 ajax 请求,easy.js 直接将 ajax 方法封装成了 promise 对象,可以直接添加 then 方法来回调。
url : &test1.php&,
type : &GET&
then(function(){
// 添加请求成功的回调
}, function(){
// 添加请求失败的回调
then 方法接受2个函数作为参数,第一个函数是已完成的回调,第二个就是已失败的回调。
如果有上面提到的多个 ajax 请求的情况呢?那么就要用到 when 这个方法了。该方法可以接受多个 promise 实例作为参数。
var requests = E.when(E.ajax({
url : &test1.php&,
type : &GET&
}), E.ajax({
url : &test2.php&,
type : &GET&
requests.then(function( arg1, arg2 ){
console.log( &success:& + arg1[0] + arg2[0] );
}, function( arg1, arg2 ){
console.log( &failure:& + arg1 + arg2 );
when 方法是将多个 promise 实例存到一个数组中,等到该数组的所有 promise 实例都是已完成状态才去执行已完成的回调,一旦有一个实例是已拒绝的状态,则立即执行已拒绝的回调。
Promise 模式是&CommonJS&的规范之一。很多主流的 JavaScript 库都有相应的实现,如 jQuery 和 Dojo 中,都有 Deferred 去实现这些功能。在这里还是要吐槽下 jQuery 的 Deferred,撇开其内部使用,这应该用户使用率最低的一个模块了,这和其较复杂的使用方式有一定的关系。
如果你想深入的研究 easy.js 的 promise 源码,可以查看。
文章来源:
最新图文推荐
最新专栏文章
大家感兴趣的内容
网友热评的文章
seajs.config({
base: "/resource/passapi/scripts/"
seajs.use('seajs/seajs-css');
seajs.use(['artdialog/src/dialog-plus'], function (dialog) {
$('#favorite').on('click', function(){
$.getJSON('/passapi.ashx?op=userstatus&callback=?', function(data){
if (data.status == 1) {
var _this = $('#favorite').find('span');
$.getJSON('/?app=favorite&controller=favorite&action=add&jsoncallback=?&contentid='+contentid, function(json){
if(json.state){
_this.html('promise(Q)的使用方法 - CNode技术社区
这家伙很懒,什么个性签名都没有留下。
最近写的一段代码中因为多次需要依靠回调函数的返回值进行下一次回调,代码看起来十分的不好看,就想着去借助promise(Q)去优化一下代码,但是看了文档,还是一头雾水啊,例如下面的代码:
request.get(uri,function(err,res,body){
request.post({
uri: uri1,
form: body
},function(err,res,body1){
request.post({
uri: uri2,
form: body1
},function(err,res,body2){
//do something
如果用Q来写的话,该怎么写啊?
找到了个很不错的
promise 的话
这个更好用…
看到Q就喷一次,比他好的太多了。推荐bluebird,API简洁,功能强大,尤其是它的promisifyAll方法
楼主的方法用bluebird的示例:
var Promise = require('bluebird')
var request = require('request')
Promise.promisifyAll(request)
//开始飞吧
request.getAsync(url).spread(function(res, body1){
return request.postAsync({uri: uri1, form: body1})
}).spread(function(res, body2){
return request.postAsync({uri: uri2, form: body2})
}).spread(function(res, body3){
//code with results
}).error(function(){
//handle error here
呃,怎么都不喜欢Q么?
最近刚刚看了下Q的文档,尝试一下,有错误请指正。
var Q = require('q');
var request = require('request');
var r = function () {
var wrap = function (result) {
// nfapply 包装的promise会将传递 [res, body]
return result[1];
// 这里返回一个包装好的promise
return Q.nfapply(request, arguments).then(wrap);
var promise =
r({uri: uri})
.then(function (body) {
return r({method: 'POST', uri: uri1, form: body});
.then(function (body1) {
return r({method: 'POST', uri: uri2, form: body1});
// 接下来
promise.then(function (body2) {
// do something
}, function (err) {
// handle err
bluebird不错,学习了。
q很好,一直用,直到发现了co yield,推荐你换换,不能更简单了
自豪地采用
CNode 社区为国内最专业的 Node.js 开源技术社区,致力于 Node.js 的技术研究。
服务器赞助商为
,存储赞助商为
,由提供应用性能服务。
新手搭建 Node.js 服务器,推荐使用无需备案的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()却只是被调用一次。
| 网站地图 | 设为首页简要介绍:ES6中,可以通过promise来处理回调函数,回调函数经常用于异步操作中,间接来说,可以通过promise优化异步操作。
1.什么是JS中的回调函数?
回调函数是作为参数传递给另外一个函数,并且改回调函数在函数主题执行完后再执行。举例来说:
function callback(m,n){
alert("我是回调函数,我在执行");
return m+n
function myFunction(callback){
return callback(1,2);
上述就是一个回调函数的例子,callback为回调函数,我们来看函数myFunction的执行过程,先执行函数的主题,最后再执行回调函数callback。
2.常见的回调函数以及存在的缺陷
(1)常见回调:
我们在jquery的ajax请求中,可以看到回调的身影,比如:
url:'...',
method:'get',
success:function(json){
经典的封装后的ajax请求就是一个,success后面所跟的函数就是一个回调函数。
(2)存在问题
因为JS是异步的,通过回调函数异步操作,会造成回调函数的嵌套,很影响代码的可读性,下面来看回调函数嵌套的情况。
url:'...',
method:'get',
success:function(json){
ajax(function(json){
上述我们看到,当最外层请求成功之时,会调用第一个回调函数,而第一个回调函数里面又嵌套了第二个异步的回调函数,如此层层嵌套,代码的可读性大大的下降。
3.promise处理回调嵌套
(1)什么是promise
promise通常用于处理函数的异步调用,通过链式调用的方式,使得代码更加直观,举例来说:
var myPromise=function(tag){
return new Promise(function(resolve,reject){
resolve('默认参数success');
reject('默认参数filed');
myPromise(true).then(function(message){
console.log(message)
//"输出默认参数success"
我们可以看到设置promise只要new Promise()就可以,并且接受一个函数,该函数里面会执行resolve()方法,表示异步调用成功时执行,reject()表示异步调用失败时候调用。
在链式调用时候,then后面接的第一个函数为成功之时调用的函数——resolve,并且这里的默认参数等同于promise中resolve中的初始参数。
(2)then和catch
then:可以在promise中实现链式调用,在上文中已经介绍。补充,then里面的第二个函数,为异步调用失败之时执行,接上面的例子:
myPromise(false).then(null,function(err){
console.log(err)
catch:catch方法,相当于then(null,function(err){console.log(err)}失败方法调用的一个缩写。
myPromise(false).catch(function(err){console.log(err)})
(3)Promise.all
Promise.all 可以接收一个元素为 Promise 对象的数组作为参数,当这个数组里面所有的 Promise 对象都变为 resolve 时,该方法才会返回。
var p1 = new Promise(function (resolve) {
setTimeout(function () {
resolve("Hello");
var p2 = new Promise(function (resolve) {
setTimeout(function () {
resolve("World");
Promise.all([p1, p2]).then(function (result) {
console.log(result);
Promise在定义的时候,在new的时候就会执行一次,因此如果要构造ajax请求可以在new Promise里传递的这个函数内进行,在定义这个构造Promise的函数里面,可以判断什么时候是执行resolve,什么时候执行reject。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:31222次
排名:千里之外
原创:50篇
评论:15条
(4)(7)(6)(1)(3)(2)(4)(7)(5)(2)(9)(5)}

我要回帖

更多关于 promise 回调函数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信