在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调用的常见操作序列,
-
进行asynchronous呼叫。
-
向呼叫者返回一个
Promise
。 -
此时,呼叫者不必等待结果。 它可以简单地定义一个
then
函数,当数据准备就绪时,它知道该做什么,然后继续下一个任务。 -
稍后的时间点,解决(或拒绝,如果失败)的承诺,当你从asynchronous调用的结果。
-
在
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 });