在节点中运行一系列异步函数需要在哪里?

时间:2015-03-10 12:37:49

标签: javascript node.js meteor future

以前,我已经使用future.wait()等待一个值return到下一个函数。 (顺便说一下,我在Meteor中编码)

在读取节点的非阻塞I / O架构之后,我的以下方法(确实有效)是否完全失败了?

我正在做的是将来自以下'requests'函数的返回结果传递给另一个函数。相反,回调方法是最好的惯例吗?

我使用future的唯一原因是因为使用return会立即执行。我想学习最佳实践,因为我认为我正在使用future添加额外的不必要代码层。

如果我使用回调约定callback(null, result),'回调'是否等待将对象传递给参数?

我的代码使用future等待结果:

function requesting(perm_data) {
  var f = new future();
  request.get('example.com/api/auth_user', {
    oauth: {consumer_key:'somekey',
            token: perm_data.oauth_token,
            token_secret: perm_data.oauth_token_secret
            }
  }, function response(error, response, body) {
  if (!error && response.statusCode === 200) {
    var bodyToJson = parser.toJson(body, options)
    var userId = bodyToJson.user.id
       return f.return(userId)
  }
  else {
    f.throw(error)
  }
})
  return f.wait()
}


function nextFunction(data) {
 //do some thing with data
 } 

Meteor.methods({
 sequenceAsyncFunctions: function() {
  try {
     var resultOne = requesting()
     var resultTwo = nextFuntion(resultOne)
      } catch (e) {
      //handling my errors
      }
  }
})

2 个答案:

答案 0 :(得分:2)

  

'回调'等待对象传递给参数

实际上回调不会等待对象。回调是通过您给它的函数的参数调用的。


你可以使用 promise 库之一,例如Q来处理这个

以下是一些更深入地描述它的文章

有些替代方案是KewAsync

已指定Promise,您可以在此处查看更多详细信息和库:http://wiki.commonjs.org/wiki/Promises/A

答案 1 :(得分:1)

我注意到你标记了这个问题。 Meteor在服务器上使用Fibers。该软件包使用一种轻量级线程(称为光纤)为您提供协作式多任务处理。这允许你写"阻止"像requesting这样的函数没有实际阻塞事件循环。 Future允许您使用Fibers以阻塞方式使用基于回调的node.js函数。

如果没有Fibers,就不可能编写像requesting那样执行I / O并直接返回结果的函数。相反,你必须通过回调(或使用承诺)。

惯用的流星代码应该利用服务器上的光纤来阻止"功能。这就是核心Meteor API的工作方式,并且在Meteor方法中是必需的。您可能会发现future更方便,而非使用Meteor.wrapAsync

在常规node.js代码中,您可以使用Fibers,但使用function (err, result) {...}回调或承诺更常见。在浏览器(包括Meteor客户端代码)中,您不能使用Fibers,因此您必须使用回调或承诺。

以下是使用future,常规回调和承诺对操作进行排序的方法:

// Future
function doTwoThings() {
    var future = new Future();
    asyncFunction(argument, function (err, result) {
        if (err) future.throw(err);
        else future.return(result);
    });
    var result = future.wait();

    var future2 = new Future();
    anotherAsyncFunction(result, function (err, result2) {
        if (err) future2.throw(err);
        else future2.return(result2);
    });
    var result2 = future2.wait();
    return result2 + 2;
}

// wrapAsync
var wrappedAsyncFunction = Meteor.wrapAsync(asyncFunction);
var wrappedAnotherAsyncFunction = Meteor.wrapAsync(anotherAsyncFunction);
function doTwoThings() {
    var result = wrappedAsyncFunction(argument);
    var result2 = wrappedAnotherAsyncFunction(anotherAsyncFunction);
    return result2 + 2;
}

// Regular callbacks
function doTwoThings(callback) {
    asyncFunction(argument, function (err, result) {
        if (err) return callback(err);

        anotherAsyncFunction(result, function (err, result2) {
            if (err) return callback(err);
            callback(null, result2 + 2);
        });
    });
}

// Promises
function doTwoThings() {
    return asyncFunctionReturningPromise(argument).then(function (result) {
        return anotherAsyncFunctionReturningPromise(result);
    }).then(function (result2) {
        return result2 + 2;
    });
}