当要使用承诺延期功能 [英] When to make a function deferred using Promises
问题描述
我使用的承诺在Q节点库的问题,我觉得可以向蓝鸟LIB为好。
上下文
我有几个函数调用,使这两个我自己的自定义功能和node.js的 FS
风格的异步功能。
如果我打电话给这样的功能:
同步功能
块引用>do_something =功能(输入){
//分配变量,做其他的东西同步
}和需要上面发生
之前
此功能:
同步功能
块引用>do_something_else的=功能(输入){
//变量赋值,做其他的东西同步
}和
然后
需要调用类似于本地节点的功能:
异步函数
块引用>writeData =功能(OBJ,回调){
VAR递延= Q.defer();
fs.writeFile(obj.file,obj.datas,功能(错了,结果){
如果(ERR)deferred.reject(ERR);
其他deferred.resolve('完成写入数据');
});
返回deferred.promise.nodeify(回调);
}和
最后
需要上面发生之前
此功能:
同步功能
块引用>do_something_last =功能(输入){
//变量赋值,做其他的东西同步
}问题
是正确的事情在这里,让我的所有功能延迟或许诺知道这样我就可以确保他们被称为顺序或按正确的顺序?
像这样:do_something(变量)
。然后(do_something_else的)
。然后(writeData)
。然后(do_something_last)
.done();或者我应该只是做这个代替,并保持排序(排序)?像这样:
VAR变量1 ='test1.txt的'
VAR变量2 ='的test2.txt'
VAR RETURN_VALUE = do_something(变量1);
VAR return_another_value = do_something_else的(RETURN_VALUE); < - 同步
writeData(return_another_value); < - 异步功能
VAR final_value = do_something_last(变量2); < - 同步功能
//可能有异步同步调用后再次调用
writeDataAgain(return_another_value); < - 异步功能澄清
我认为是因为其中的一些功能,同步将需要异步之后被解雇,我需要让他们为了保持序列直,像这样无极意识到:
同步功能所做的承诺,认识到
块引用>do_something =功能(输入){
VAR递延= Q.defer();
//分配变量,做其他的东西同步
deferred.resolve(_output_result_);
返回deferred.promise;
}
do_something_else的=功能(输入){
VAR递延= Q.defer();
//分配变量,做其他的东西同步
deferred.resolve(_output_result_);
返回deferred.promise;
}
do_something_last =功能(输入){
VAR递延= Q.defer();
//分配变量,做其他的东西同步
deferred.resolve(完成工作流');
返回deferred.promise;
}这将使我做到这一点:
do_something(变量)
。然后(do_something_else的)LT; - 这些都需要writeData前执行
。然后(writeData)LT; - 一个异步节点FS调用WriteFile的
。然后(do_something_last)LT; - 我需要这在writeDate发生后,
.done();反馈我读过之后,我猜好像我真的问的是:
我如何创建一个函数的工作流程,混合非承诺同步和
承诺感知异步函数调用,同时保持所有的订货
执行(或排序)?
块引用>解决方案
只是做这个代替,并保持有序,像这样:
writeData(return_another_value);
VAR final_value = do_something_last(变量2);
块引用>嗯,这是行不通的,因为
do_something_last
的writeData(...)
承诺后不叫是的解决的。创建并返回后,承诺它会刚开始的权利。所以,如果你关心这个特定的顺序,并希望等到数据被写入,那么你的需求的使用然后
有一个回调:VAR final_promise = writeData(return_another_value)。然后(功能(writeResult){
返回do_something_last(变量2);
});的一般规则是:
- 请同步功能同步 - 无需承诺
- 请所有异步函数总是返回一个承诺
- 使用在尽可能低的水平 promisification
仅deferreds您可以只放在一个
然后
链 同步功能,无承诺返回值(甚至抛出的异常)工作,他们的罚款。
所以,当你的可以的写序列,例如Q(test1.txt的')
。然后(do_something)
。然后(do_something_else的)
。然后(writeData)
。然后(do_something_last.bind(空'的test2.txt'))
.done();它看起来相当奇怪。如果你不打算让
do_something
■在不久的将来,异步出于某种原因,它往往是简单的写入和读取writeData(do_something_else的(do_something('test1.txt的')))。然后(函数(){
返回do_something_last('的test2.txt');
})()完成。诚然,它有时更具吸引力写
somePromise()
。然后(doSomethingSynchronous)
。然后(doSomethingAsynchronous)比
somePromise
。然后(功能(RES){返回doSomethingAsynchronous(doSomethingSynchronous(RES));})即使它们的功能相同。选择你喜欢的更好,这是比较一致的风格。
I'm using the Q node library for Promises, question I think can apply to the Bluebird lib as well.
Context
I have a few function calls to make to both my own custom functions and node.js
fs
style async functions.if I'm making a call to a function like this:
sync function
do_something = function (input) { // assign variables, do other sync stuff }
and need the above to take place
before
this function:sync function
do_something_else = function (input) { // assign variable, do other sync stuff }
and
then
need to call a native node function similar to:async function
writeData = function (obj, callback) { var deferred = Q.defer(); fs.writeFile(obj.file, obj.datas, function (err, result) { if (err) deferred.reject(err); else deferred.resolve('write data completed'); }); return deferred.promise.nodeify(callback); }
and
finally
need the above to take placebefore
this function:sync function
do_something_last = function (input) { // assign variable, do other sync stuff }
Question
Is the 'right' thing to do here, to make all my functions 'deferred' or promise aware so I can make sure that they are called in sequence or in the correct order? like so:
do_something(variable) .then(do_something_else) .then(writeData) .then(do_something_last) .done();
or should I just do this instead and keep the ordering (sequencing)? Like so:
var variable1 = 'test1.txt' var variable2 = 'test2.txt' var return_value = do_something(variable1); var return_another_value = do_something_else(return_value); <--sync writeData(return_another_value); <-- async function var final_value = do_something_last(variable2); <-- sync function // could potentially have async calls again after a sync call writeDataAgain(return_another_value); <-- async function
Clarifications
What I thought was since some of these sync functions are going to need to be fired after the async, I needed to make them Promise aware in order to keep the sequence straight, like so:
sync functions made promise aware
do_something = function (input) { var deferred = Q.defer(); // assign variables, do other sync stuff deferred.resolve(_output_result_); return deferred.promise; } do_something_else = function (input) { var deferred = Q.defer(); // assign variables, do other sync stuff deferred.resolve(_output_result_); return deferred.promise; } do_something_last = function (input) { var deferred = Q.defer(); // assign variables, do other sync stuff deferred.resolve('completed workflow'); return deferred.promise; }
this would allow me to do this:
do_something(variable) .then(do_something_else) <-- these need to execute before writeData .then(writeData) <-- a async node fs call to writeFile .then(do_something_last) <-- I need this to happen after the writeDate .done();
After the feedback i've read, i guess what it seems like i'm really asking is:
How do I create a function workflow, mixing non-promise sync and promise-aware async function calls, all the while keeping the ordering (or sequencing) of execution?
解决方案just do this instead and keep the ordering like so:
writeData(return_another_value); var final_value = do_something_last(variable2);
Well, that simply won't work, as
do_something_last
is not called after thewriteData(…)
promise is resolved. It'll just start right after the promise is created and returned. So if you care about that particular order and want to wait until the data is written, then you need to usethen
with a callback:var final_promise = writeData(return_another_value).then(function(writeResult) { return do_something_last(variable2); });
The general rules are:
- make synchronous functions synchronous - no need for promises
- make all asynchronous functions always return a promise
- use deferreds only at the lowest possible level for promisification
You can just place synchronous functions in a
then
chain, non-promise return values (or even thrown exceptions) work fine in them. So while you can write your sequence likeQ('test1.txt') .then(do_something) .then(do_something_else) .then(writeData) .then(do_something_last.bind(null, 'test2.txt')) .done();
it looks rather odd. If you don't plan to make the
do_something
s asynchronous in the near future for some reason, it's often simpler to write and readwriteData(do_something_else(do_something('test1.txt'))).then(function() { return do_something_last('test2.txt'); }).done();
Admittedly, it's sometimes more appealing to write
somePromise() .then(doSomethingSynchronous) .then(doSomethingAsynchronous)
than
somePromise .then(function(res) { return doSomethingAsynchronous(doSomethingSynchronous(res)); })
even though they are functionally identical. Choose the style that you like better and that is more consistent.
这篇关于当要使用承诺延期功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!