如何将参数传递给“then”函数

4

我正在尝试学习使用延迟对象,但是在"then"块中,我没有得到预期的参数,感到困惑。

var makeCall = function (err, param) {
  var deferred = Q.defer();
  setTimeout(function() {
    console.log(1111, err, param);
    deferred.resolve(err, param);
  }, 1000);
  return deferred.promise;
};

makeCall('test', '11').then(function(err, data) {
  console.log(222, err, data);
});

使用Console.函数,1111输出了从Ajax调用返回的正确数据,但是222没有。

http://jsfiddle.net/M2V44/


实际上,我同时得到了1111222 - thefourtheye
抱歉,我应该更清楚一些。我确实按正确顺序获得了1111和222,但数据的内容是不正确的。1111显示有效数据,但222显示为空。 - Anatoli
非常抱歉,我们无法重现这个问题。您能否创建一个 jsFiddle? - thefourtheye
如何在 jsFiddle 中添加 q 是最佳方式? - Anatoli
1
@CodingTwinky,你不应该使用deferred对象,而应该使用Promise构造函数,通过Q.Promise暴露出来 - 这样更安全,也更可取。 - Benjamin Gruenbaum
显示剩余3条评论
3个回答

5

deferred.resolve 只能接受一个参数,用于标记异步调用的成功。要通知失败,您需要使用 deferred.reject。因此,您的代码必须更改如下:

var makeCall = function(err,param){
    setTimeout(function () {
        console.log(1111, err, param);
        var deferred = Q.defer();
        if (err) {
            deferred.reject(err);
        } else {
            deferred.resolve(param);
        }
    }, 1000);
    return deferred.promise;
};

makeCall(undefined, '11').then(function (data) {
    console.log(222, data);
}, function (err) {
    console.log(333, err);
});

这将打印222 '11',为了模拟失败的情况,只需使用任何"真值"作为第一个参数调用makeCall。例如:
makeCall('11')....

如果出现错误,它将调用失败处理程序,并输出333 '11'


2
在您的情况下,我建议完全避免使用deferred。
var makeCall = function(err,param){
    if(err) return Q.reject(err);
    return Q(param).delay(1000);
};

(fiddle)

这个使用方法与之前的foureye的答案相似,因为承诺是像同步代码一样的,你可以使用返回值和catch语句与它们交互。 Nodebacks((err,data))和回调通常会从异步代码中删除许多理想的属性,而承诺旨在恢复这些属性。

makeCall(new Error("Hello"),"SomeValue").then(function(cata){
    console.log("Got correct data!",data);
}).catch(function(err){
    console.log("Got error :(",err); // this would happen since we passed an error.
});

我还假设这个函数是虚构的,不代表一个真实的API。

在将API转换为promises时,您主要使用延迟对象,但在这种情况下您不需要。


1
注意,a) 不确定是否正确解释问题; b) Promise 在每个浏览器中似乎没有统一实现,也不在 jsfiddle 中。这可能会有所帮助 JavaScript Promises http://www.html5rocks.com/en/tutorials/es6/promises/ (下面的代码可以在控制台中尝试;也应该在 mozilla nightly 控制台中工作,这里似乎实现了 Promise 对象)。
请尝试这个(模式)。
var makeCall = function(err, param) {    
return new Promise(function(resolve, reject ) {   
setTimeout(function() {
  console.log(1111, err, param);    
  return (err && param) ?
    resolve(err, param)  :  
    reject(Error("error"))      
  })
  }, 1000);
};        
makeCall("test", "11")
.then(function(result) {
console.log(222, result);
makeCall("test2","11");
makeCall("abc", 123) // `chain` test
}, 
function(err) {
console.log(err)
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接