在parsing之前返回的延迟对象

我正在使用带有Node js的库。 我创build一个被caching的对象,把这个parsing放到一个封装的Mongoose findOne()函数中,然后在外面返回promise。 但似乎我的承诺总是在数据被检索之前返回。

User.prototype.getProfile = function(criteria) { var deferred = when.defer(); var options = { criteria: criteria, select: 'name id email' }; this.User.load(options, function(err, data) { if (data) { this.name = data.name; this.email = data.email; this.id = data.id; } else { return false; } console.log(data); deferred.resolve(); }); console.log('returning promise'); return deferred.promise; }; 

呼叫者

 User.getProfile(req.query).then( function success(data) { res.send('Hello ' + User.name);// Hello '' } ); 

data之前输出'returning promise'

是的,承诺将返回给调用者而不是数据,这就是我们如何利用asynchronousfunction。 这是处理asynchronous调用的常见操作序列,

  1. 进行asynchronous呼叫。

  2. 向呼叫者返回一个Promise

  3. 此时,呼叫者不必等待结果。 它可以简单地定义一个then函数,当数据准备就绪时,它知道该做什么,然后继续下一个任务。

  4. 稍后的时间点,解决(或拒绝,如果失败)的承诺,当你从asynchronous调用的结果。

  5. Promise对象上执行then函数,并使用asynchronous调用的结果。

所以,你的代码将不得不被修改一下,像这样

 User.prototype.getProfile = function(criteria) { var deferred = when.defer(); var options = { criteria: criteria, select: 'name id email' }; this.User.load(options, function(err, data) { if (err) { // Reject, if there is an error deferred.reject(err); } else { // Resolve it with actual data deferred.resolve(data); } }); return deferred.promise; }; 

那么你的来电者会做这样的事情

 userObject.getProfile() .then(function(profileObject) { console.log(profileObject); // Do something with the retrieved `profileObject` }) .catch(function(err) { console.err("Failed to get Profile", err); }); // Do something else here, as you don't have to wait for the data 

在这里,调用者只是调用getProfile并附加一个函数,说明如何处理返回的数据并继续前进。


编辑如果你想同一个对象被更新,那么你可以简单地使用类似的代码,但是你需要保留this在其他variables,因为绑定this发生在运行时。

 User.prototype.getProfile = function(criteria) { var deferred = when.defer(); var options = { criteria: criteria, select: 'name id email' }; var self = this; this.User.load(options, function(err, data) { if (err) { // Reject, if there is an error deferred.reject(err); } else { self.name = data.name; self.email = data.email; self.id = data.id; } deferred.resolve(data); }); return deferred.promise; }; 

这就是promises工作原理。

由于你有一个需要一段时间的asynchronous任务,并且JavaScript是单线程语言,所以你不想阻塞你的代码,等待asynchronous操作完成 – 否则没有人会使用JavaScript

所以你会怎么做? 您创build一个promise并继续您的代码。
您将callback添加到该promise ,当承诺解决您的callback被调用。

没有使用when库,但你想要做的是这样的:

 User.prototype.getProfile = function(criteria){ var deferred = when.defer(); var options = { criteria : criteria, select : 'name id email' }; this.User.load(options, function(err, data) { if (data) { this.name = data.name; this.email = data.email; this.id = data.id; console.log(data); // the callback will invoke after the deferred object is resolved. deferred.promise.then(function(o){ console.log('resolved!!!'); }); deferred.resolve(data); }else{ deferred.reject('something bad occured'); return false; } }); return deferred.promise; }; 

尽量避免使用延迟模式( 请参阅此处 )。

when.js支持显示构造函数模式 ,这也导致更多的可读代码。

 User.prototype.getProfile = function(criteria) { var self = this; var options = { criteria: criteria, select: 'name id email' }; return when.promise(function(resolve, reject) { self.User.load(options, function(err, data) { if (err) { reject(err); } self.name = data.name; self.email = data.email; self.id = data.id; resolve(); // or resolve(data) }); }); }; 

下一个

 userObject.getProfile() .then(function() { // data loaded }) .catch(function(err) { // something went wrong, process the error });