假设您维护一个公开函数的库getData
.您的用户将其调用以获取实际数据:
var output = getData();
在引擎盖下,数据保存在文件中,因此您getData
使用内置的Node.js 实现fs.readFileSync
.很明显这两个getData
和fs.readFileSync
是同步的功能.有一天,您被告知要将基础数据源切换到MongoDB等只能异步访问的仓库.您还被告知要避免惹恼您的用户,getData
不能更改API以仅返回承诺或要求回调参数.你如何满足这两个要求?
使用回调/保证的异步函数是JavasSript和Node.js的DNA.任何非平凡的JS应用程序都可能充满了这种编码风格.但这种做法很容易导致所谓的厄运金字塔回调.更糟糕的是,如果调用链中任何调用者中的任何代码都依赖于异步函数的结果,那么这些代码也必须包含在回调函数中,对调用者施加编码样式约束.我不时发现需要将异步功能(通常在第三方库中提供)封装到同步功能中,以避免大规模的全局重新分解.搜索关于此主题的解决方案通常最终得到Node Fibers或从中派生的npm包.但纤维无法解决我所面临的问题.甚至纤维作者提供的例子说明了这一缺陷:
...
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
Run Code Online (Sandbox Code Playgroud)
实际产量:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
Run Code Online (Sandbox Code Playgroud)
如果函数Fiber确实将异步函数sleep转为同步,则输出应为:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
back in …
Run Code Online (Sandbox Code Playgroud) 我在server/statusboard.js中有以下代码;
var require = __meteor_bootstrap__.require,
request = require("request")
function getServices(services) {
services = [];
request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) {
var resJSON = JSON.parse(body);
_.each(resJSON, function(data) {
var host = data["host_name"];
var service = data["service_description"];
var hardState = data["last_hard_state"];
var currState = data["current_state"];
services+={host: host, service: service, hardState: hardState, currState: currState};
Services.insert({host: host, service: service, hardState: hardState, currState: currState});
});
});
}
Meteor.startup(function () {
var services = [];
getServices(services);
console.log(services);
});
Run Code Online (Sandbox Code Playgroud)
基本上,它从JSON提要中提取一些数据并尝试将其推送到集合中.
当我启动Meteor时,我得到以下异常;
app/packages/livedata/livedata_server.js:781
throw exception;
^
Error: Meteor …
Run Code Online (Sandbox Code Playgroud) 代码是不是通过同步来提高效率?为什么编码同步获胜?我在做一些研究时找到了这两个链接:http://bjouhier.wordpress.com/2012/03/11/fibers-and-threads-in-node-js-what-for/,https : //github.com /贤者/ streamlinejs /
如果目标是防止意大利面条代码,那么显然你可以使用例如streamline.js的异步代码,这不是回调金字塔,对吧?
我在使用Fibers/Meteor.bindEnvironment()时遇到了困难.如果集合开始为空,我尝试更新代码并插入集合.这应该是在启动时运行服务器端.
function insertRecords() {
console.log("inserting...");
var client = Knox.createClient({
key: apikey,
secret: secret,
bucket: 'profile-testing'
});
console.log("created client");
client.list({ prefix: 'projects' }, function(err, data) {
if (err) {
console.log("Error in insertRecords");
}
for (var i = 0; i < data.Contents.length; i++) {
console.log(data.Contents[i].Key);
if (data.Contents[i].Key.split('/').pop() == "") {
Projects.insert({ name: data.Contents[i].Key, contents: [] });
} else if (data.Contents[i].Key.split('.').pop() == "jpg") {
Projects.update( { name: data.Contents[i].Key.substr(0,
data.Contents[i].Key.lastIndexOf('.')) },
{ $push: {contents: data.Contents[i].Key}} );
} else {
console.log(data.Contents[i].Key.split('.').pop());
}
}
});
} …
Run Code Online (Sandbox Code Playgroud) 我带来了一些带有无限循环的JS代码(我们使用节点光纤来发生事情).
ESLint讨厌:
while (true) {
}
Run Code Online (Sandbox Code Playgroud)
因为条件不断.
但是允许以下内容:
for(;;) {
}
Run Code Online (Sandbox Code Playgroud)
不仅仅是喂养lintbeast,有什么客观原因,以有利于for
在while
(反之亦然)?
注意:这个问题明确要求客观原因,因此不仅仅是基于意见.
我一直在试图弄清楚如何使用node-fiber来使我的数据库代码在node.js中不那么混乱,但我无法让它工作.我将代码简化为最小测试用例:
var Future = require('fibers/future');
var pg=require('pg');
var connstr = "pg://not_the_real_user:or_password@localhost/db";
var pconnect = Future.wrap(pg.connect);
Fiber(function() {
var client = pconnect(connstr).wait();
console.log("called function");
}).run();
Run Code Online (Sandbox Code Playgroud)
如果我保持原样,我会收到以下错误:
pgfuture.js:10
}).run();
^
TypeError: undefined is not a function
at Object.PG.connect.pools.(anonymous function).genericPool.Pool.create (/home/erik/code/treehouse-node/node_modules/pg/lib/index.js:49:20)
at dispense (/home/erik/code/treehouse-node/node_modules/pg/node_modules/generic-pool/lib/generic-pool.js:223:17)
at Object.exports.Pool.me.acquire (/home/erik/code/treehouse-node/node_modules/pg/node_modules/generic-pool/lib/generic-pool.js:267:5)
at PG.connect (/home/erik/code/treehouse-node/node_modules/pg/lib/index.js:75:15)
at Future.wrap (/home/erik/code/treehouse-node/node_modules/fibers/future.js:30:6)
at /home/erik/code/treehouse-node/pgfuture.js:8:18
Run Code Online (Sandbox Code Playgroud)
但是,如果我注释掉调用pconnect的行,我在控制台上得到"被调用的函数"消息并且没有错误.github页面上的示例具有几乎相同的结构,并且它在我的系统上正常工作,但我很困惑我在这里做错了什么.
编辑:其他详细信息
我已经设法让代码以一种似乎无关的两种不同方式运行,但两者都有相同的行为.函数完成后,节点只挂起,我必须用ctrl-c杀死它.以下是我为获得该结果所做的两件事:
1)在匿名函数中包装pg.connect,然后用Future包装THAT:
pconnect = Future.wrap(function(err,cb){pg.connect(err,cb);});
Run Code Online (Sandbox Code Playgroud)
2)这个是一个真正的谜,但似乎有相同的结果.在光纤内部,我只是在调用pconnect之前直接调用pg.connect,一切似乎都解决了.
// add this line before call to pconnect
pg.connect(connstr, function(e,c){console.log("connected.");});
// and now the original call to pconnect
var client …
Run Code Online (Sandbox Code Playgroud) 我正在处理一个旧的节点项目,在执行 npm install 时出现错误
节点版本:v13.8.0 Npm 版本:6.14.4 Mac OS 版本:10.15.5
起初,我在重新安装 X-Code 后遇到了已修复的 X-Code 问题。
该问题似乎在 npm 页面上,但没有人回复
> fibers@2.0.2 install /Users/cksharma/projects/step-library/some-library/node_modules/fibers
> node build.js || nodejs build.js
CXX(target) Release/obj.target/fibers/src/fibers.o
../src/fibers.cc:68:2: error: no template named 'Handle'
Handle<String> NewLatin1String(Isolate* isolate, const char* string) {
^
../src/fibers.cc:69:10: error: no viable conversion from returned value of type 'Local<v8::String>' to function return type 'int'
return String::NewFromOneByte(isolate, (const uint8_t*)string, NewStringType::kNormal).ToLocalChecked();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/fibers.cc:72:2: error: no template named 'Handle'
Handle<String> NewLatin1Symbol(Isolate* isolate, const char* string) …
Run Code Online (Sandbox Code Playgroud) 在尝试部署meteor时,我通过以下方式安装节点光纤:
$ cd bundle/server
Run Code Online (Sandbox Code Playgroud)
然后安装光纤
$ npm install fibers
Run Code Online (Sandbox Code Playgroud)
它似乎安装但有这条消息:
`linux-x64-v8-3.14` exists; testing
Binary is fine; exiting
fibers@1.0.1 node_modules/fibers
Run Code Online (Sandbox Code Playgroud)
但是,在使用以下代码部署代码时:
node bundle/main.js
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
throw new Error('`'+ modPath+ '.node` is missing. Try reinstalling `node-fibe
~/main_repo/bundle/server/node_modules/fibers/bin/linux-x64-v8-3.20/fibers.node` is missing. Try reinstalling `node-fibers`?
Run Code Online (Sandbox Code Playgroud)
我可以看到linux-x64-v8-3.xx的版本不同.我正在使用Ubuntu 13.04
节点版本为v0.11.3,NPM版本为1.2.18
我是第一次制作一个相当简单的流星应用程序,它应该查询来自某个仓库的所有git问题.在从github api获取问题列表之后,我们的想法是从这些问题中创建一组任务.但是,每当我尝试查询当前任务列表时,我得到:
.../.meteor/tools/c2a0453c51/lib/node_modules/fibers/future.js:83
W20140418-17:00:43.872(-7)? (STDERR) throw new Error('Can\'t wait without a fiber');
W20140418-17:00:43.872(-7)? (STDERR) ^
W20140418-17:00:43.889(-7)? (STDERR) Error: Can't wait without a fiber
W20140418-17:00:43.889(-7)? (STDERR) at Function.wait
(.../.meteor/tools/c2a0453c51/lib/node_modules/fibers/future.js:83:9)
W20140418-17:00:43.890(-7)? (STDERR) at Object.Future.wait
(.../.meteor/tools/c2a0453c51/lib/node_modules/fibers/future.js:325:10)
W20140418-17:00:43.890(-7)? (STDERR) at _.extend._nextObject (packages/mongo-
livedata/mongo_driver.js:805)
W20140418-17:00:43.890(-7)? (STDERR) at _.extend.forEach (packages/mongo-livedata/mongo_driver.js:836)
W20140418-17:00:43.890(-7)? (STDERR) at Cursor.(anonymous function) [as forEach] (packages/mongo-
livedata/mongo_driver.js:695)
W20140418-17:00:43.890(-7)? (STDERR) at app/server/publish.js:51:33
W20140418-17:00:43.890(-7)? (STDERR) at Array.forEach (native)
W20140418-17:00:43.891(-7)? (STDERR) at app/server/publish.js:49:19
W20140418-17:00:43.891(-7)? (STDERR) at
...packages/npm/.build/npm/node_modules/github/api/v3.0.0/issues.js:116:17
W20140418-17:00:43.891(-7)? (STDERR) at IncomingMessage.<anonymous>
(...packages/npm/.build/npm/node_modules/github/index.js:756:21)
Run Code Online (Sandbox Code Playgroud)
我的第一个想法是,当我应该使用节点光纤时,我正在某处使用回调,但代码似乎相对简单:
var repos = ['my-repo', …
Run Code Online (Sandbox Code Playgroud) 下面的代码行是做什么的?
Npm.require('fibers/future');
Run Code Online (Sandbox Code Playgroud)
我在网上看了一些例子,我遇到了一些这样的事情:
Future = Npm.require('fibers/future');
var accessToken = new Future();
Run Code Online (Sandbox Code Playgroud)
accessToken
在这种情况下,变量会是什么?
node-fibers ×10
node.js ×7
meteor ×6
javascript ×4
npm ×2
asynchronous ×1
eslint ×1
mongodb ×1
npm-install ×1
postgresql ×1
synchronous ×1