【问题标题】:running multiple async functions sequentially in node.js在 node.js 中按顺序运行多个异步函数
【发布时间】:2015-08-06 08:54:19
【问题描述】:

我是 javascript 也是 node.js 环境的新手。 我很难使用回叫。因为当我有很多程序时 连在一起,很难写,而且会变得很讨厌。

所以,在我用谷歌搜索答案后,我找到了异步工具,但它仍然像 它可以使用回调逐块执行代码。 例如,f1 -> f2 -> f3 ...

但是,我们的服务器和我的电脑总是有延迟。 然后如果我做一些事情,比如创建桶,然后打印我得到了多少。 它会在我添加一个之后打印出原始数量的桶。 像删除桶一样的情况....有大神能帮帮我吗

谢谢...

function bucketSerialTesting(s3)
{
    async.series([
      function f1(callback)
      {
          settingBucket ('testjsbucket2',s3);
          callback('1');
      }
      ,
      function f2(callback)
      {
        settingBucket('testjsbucket3', s3);
        callback('2');
      }
      ,
      function f3(callback)
      {
        listBucket(s3);
        callback('3');
      }
      ,
      function f4(callback)
      {
          deleteBucket('testjsbucket2', s3);
          callback('4');
      }
      ,
      function f5(callback)
      {
          deleteBucket('testjsbucket3', s3);
          callback('5');
      }
      ,
      function f6(callback)
      {
          listBucket(s3);
          callback('6');
      },
    ],
    function(err, results){
        console.log(results);
    });
}



function settingBucket (bucketName, s3){
    var s3 = new AWS.S3();
    var params = {
          Bucket: bucketName, /* required */
    };
    s3.createBucket(params, function(err, data) {
     if (err) console.log(err, err.stack); // an error occurred
     else     console.log(data);           // successful response
    }).on('success',function(response)
            //put bucket cors for browsers javascript testing
            {
                var params = {
                Bucket: bucketName, /* required */
                CORSConfiguration: {
                CORSRules: [
                  {
                    AllowedHeaders: ['*',],
                    AllowedMethods: ['GET','PUT','DELETE','POST'],
                    AllowedOrigins: ['*','null'],
                    ExposeHeaders:  ['ETag',],
                   },
                ]
                },
                };
                s3.putBucketCors(params, function(err, data) {
                if (err) console.log(err, err.stack); // an error occurred
                else     {
                    console.log(data);
                    console.log('put bucketcors succeed');
                }
                });
            }).send();
}




function listBucket(s3)
{
    s3.listBuckets(function(err, data) {
          if (err) console.log(err, err.stack); // an error occurred
          else     {
            console.log(data);
            console.log('we have '+data.Buckets.length.toString()+' buckets');
            for (var i = data.Buckets.length - 1; i >= 0; i--) {
                console.log(data.Buckets[i].Name);
            };
          }           // successful response
        });
}

function deleteBucket(bucketName, s3){
    var params = {
          Bucket: bucketName, /* required */
        };
        s3.listObjectVersions(params, function(err, data) {
          if (err) console.log(err, err.stack); // an error occurred
          else{
              console.log(data);           
              params = {Bucket: bucketName};
                params.Delete = {};
                params.Delete.Objects = [];
                console.log(data.Versions.length);
                for(j = 0; j < data.Versions.length;++j)
                {
                    params.Delete.Objects.push({Key: data.Versions[j].Key,
                    VersionId: data.Versions[j].VersionId
                    });
                }
                for(j = 0; j < data.DeleteMarkers.length;++j)
                {
                    params.Delete.Objects.push({Key: data.DeleteMarkers[j].Key,
                    VersionId: data.DeleteMarkers[j].VersionId
                    });
                }
                s3.deleteObjects(params, function(err, data) {
                  if (err) console.log(err, err.stack); // an error occurred
                  else     {
                      console.log(data);
                  }
                  params = {Bucket: bucketName};
                  s3.deleteBucket(params, function(err, data) {
                      if (err) console.log(err, err.stack); // an error occurred
                      else     console.log(data);           // successful response
                    });     
                });

          }
        });
}

【问题讨论】:

  • 您调用的那些函数似乎都没有使用回调。为什么你认为你需要async.js?或者你只是叫他们错了?请链接文档或显示这些存储桶函数的定义。
  • 您的删除和列出存储桶函数调用具有回调的 s3 函数。所以你的函数需要接受回调并调用这些回调。
  • 你应该看看 Q 承诺。如果你用 defer 和 resolve/reject 包装回调函数,它会使你的代码变平很多
  • 举个例子,我们最近将一个我们必须的类转换为 Q 并且它变平了很多:github.com/Microsoft/vso-agent/blob/master/src/agent/…
  • 祝你的异步冒险好运 :)

标签: javascript node.js amazon-web-services amazon-s3 async.js


【解决方案1】:
function bucketSerialTesting(s3)
{

    Q.fcall(function f1()
    {
         return settingBucket ('testjsbucket20',s3);
    })
    .then(function f2()
    {
        return settingBucket('testjsbucket30', s3);
    }
    )
    .then(function f3()
    {
        return listBucket(s3);
    }
    )
    .then(function f4()
    {
        return deleteBucket('testjsbucket20', s3);
    }
    )
    .then(function f4()
    {
        return deleteBucket('testjsbucket30', s3);
    }
    )
    .then(function f4()
    {
        return listBucket(s3);
    }
    )
    .done();

}



function settingBucket (bucketName, s3){
    var deferred = Q.defer();
    var s3 = new AWS.S3();
    var params = {
          Bucket: bucketName, /* required */
    };
    s3.createBucket(params, function(err, data) {
     if (err) console.log(err, err.stack); // an error occurred
     else     console.log(data);           // successful response
    }).on('success',function(response)
            //put bucket cors for browsers javascript testing
            {
                var params = {
                Bucket: bucketName, /* required */
                CORSConfiguration: {
                CORSRules: [
                  {
                    AllowedHeaders: ['*',],
                    AllowedMethods: ['GET','PUT','DELETE','POST'],
                    AllowedOrigins: ['*','null'],
                    ExposeHeaders:  ['ETag',],
                   },
                ]
                },
                };
                s3.putBucketCors(params, function(err, data) {
                if (err) console.log(err, err.stack); // an error occurred
                else     {
                    console.log(data);
                    console.log('put bucketcors succeed');
                    deferred.resolve(data);
                }
                });
            }).send();
    return deferred.promise;
}




function listBucket(s3)
{
    var deferred = Q.defer();
    s3.listBuckets(function(err, data) {
          if (err) console.log(err, err.stack); // an error occurred
          else     {
            console.log(data);
            console.log('we have '+data.Buckets.length.toString()+' buckets');
            for (var i = data.Buckets.length - 1; i >= 0; i--) {
                console.log(data.Buckets[i].Name);
            };
            deferred.resolve(data);
          }           // successful response
        });
    return deferred.promise;
}

function deleteBucket(bucketName, s3){
    var deferred = Q.defer();
    var params = {
          Bucket: bucketName, /* required */
        };
        s3.listObjectVersions(params, function(err, data) {
          if (err) console.log(err, err.stack); // an error occurred
          else{
              console.log(data);           
              params = {Bucket: bucketName};
                params.Delete = {};
                params.Delete.Objects = [];
//              console.log(data.Versions.length);
                for(j = 0; j < data.Versions.length;++j)
                {
                    params.Delete.Objects.push({Key: data.Versions[j].Key,
                    VersionId: data.Versions[j].VersionId
                    });
                }
                for(j = 0; j < data.DeleteMarkers.length;++j)
                {
                    params.Delete.Objects.push({Key: data.DeleteMarkers[j].Key,
                    VersionId: data.DeleteMarkers[j].VersionId
                    });
                }
                s3.deleteObjects(params, function(err, data) {
                  if (err) {
                      console.log(err, err.stack);
                      console.log('or has no objects');// an error occurred
                  }
                  else     {
                      console.log(data);
                  }
                  params = {Bucket: bucketName};
                  s3.deleteBucket(params, function(err, data) {
                      if (err) console.log(err, err.stack); // an error occurred
                      else     {
                          console.log(data);
                          deferred.resolve(data);
                      }
                    });     
                });

          }
        });
    return deferred.promise;

}

【讨论】:

  • 太棒了。很高兴你想出来了。也不要忘记失败和鳍处理。还可以使用返回数据并传递给 next 的异步函数来使用 Q(提示 s3 应该是 arg 到 f3)。这里有很多变化和东西可以玩。超出问题的范围。
【解决方案2】:

一个选项是 Q 承诺,它确实有助于解除回调地狱并稍微扁平化您的代码。

https://github.com/kriskowal/q

延迟、解决/拒绝模式很适合您。

这是一个扁平化异步工作的示例。它打印一个文件 hello.txt(存在),等待一秒钟,在一个不存在的文件上出错,跳转到失败处理程序,然后运行 ​​finally。

var Q = require('q');
var fs = require('fs');
var path = require('path');


// a promise just defers execution of success or failure - must return the promise.  notice how it calls resolve in the callback of the async function.
var wait = function(ms) {
    var defer = Q.defer();

    console.log('waiting ' + ms + ' ms');
    setTimeout(function() {
        defer.resolve();
    }, ms);

    return defer.promise;
}

// you can wrap a node callback function with Q.defer and call reject or resolve
var getFileContents = function(path) {
    var defer = Q.defer();

    fs.readFile(path, function(err, data) {
        if (err) {
            defer.reject(err);
        }
        else {
            // can't pass multiple args back - it returns one obj
            defer.resolve({ path: path, data: data });
        }
    });

    return defer.promise;
}

var ms = 1000;

var printFile = function(filePath) {
    // even function wrapping up work returns a promise so it can be
    // connected with another outer sequence of work
    return wait(ms)
        .then(function() {
            console.log(new Date().toString());
        })
        .then(function() {
            // if you call async that returns promise, you must return it
            return getFileContents(filePath);
        })
        // the resolve data from previous promise is passed as input to next then
        .then(function(contents) {
            console.log(contents.path + ':');
            console.log(contents.data.toString());
        })
}

// sometimes you need to just return a no op based on a conditional check etc...
var noOpPromise = function() {
    console.log('no op');
    return Q(null);
}


printFile(path.join(__dirname, 'hello.txt'))
.then(function() {
    // throw new Error('throwing will jump to fail');
    return wait(1000);
})
.then(function() { 
    return printFile(path.join(__dirname, 'noexist.txt'));
})
.then(function() {
    console.log('should never get here');
})
// can also use .catch
.fail(function(err) {
    console.error('Error: ' + err.message);
})
.fin(function() {
    console.log('done with work');
})

【讨论】:

  • 非常感谢,我明天也会发布我编辑的代码。
猜你喜欢
  • 2019-08-30
  • 2021-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多