JS异步执行导致痛苦

时间:2017-04-24 02:57:26

标签: javascript node.js asynchronous promise

我正在使用NodeJS开发后端服务器代码。代码的作用是,定期连接到REST API,请求更新,然后写入我的数据库。

我无法从API中获取数据的delta,因此我从MongoDB中删除了我的集合,然后只插入新提取的数据。

我实现了promises,以确保只有在前面的方法解析后才执行依赖方法。然而,这似乎并不像我预期的那样有效。

所以,我删除了集合并插入,这是有效的。但是,在填充新数据之前,似乎执行以下方法。它有时是有效的,当我有一些新的console.log语句时,似乎会稍微引起一点点延迟,以使它全部工作。

setTimeout功能似乎没有帮助。有什么建议吗?

以下是代码的清理版本:https://jsfiddle.net/ppbfrozg/

var request = require("request");
var q = require('q');

function authenticate() {
  var deferred = q.defer();
  request(options, function(error, response, body) {
    if (error) throw new Error(error);
    deferred.resolve(JSON.parse(body).token);
  });

  return deferred.promise;
}


function getData(token) {
  var deferred = q.defer();
  request(options, function(error, response, body) {
    if (error) throw new Error(error);
    deferred.resolve(JSON.parse(body).token);

  });

  return deferred.promise;
}


function insertDataInMongo(a) {
  var deferred = q.defer();
  var MongoClient = require('mongodb').MongoClient;
  var url = 'mongodb://localhost/myDB';
  var token = a[1];
  MongoClient.connect(url, function(err, db) {
    if (err) return deferred.reject(new Error(err))
    console.log("connected for insert");


    var apiData = JSON.parse(a[0]).data;

    if (JSON.parse(a[0]).data) {


      db.collection('MediaData').insert(apiData);
      console.log("Records Inserted");
    } else {

      db.collection('Details').drop();
      db.collection('Details').insert(JSON.parse(a[0]));

      console.log("Records Inserted");
    }

    deferred.resolve(token);

  });

  return deferred.promise;
}


function getMedia(dataContext) {

  var deferred = q.defer();

  var cursor = dataContext[0];
  var token = dataContext[1];

  if (cursor !== null) {
    console.log("Inside cursor not null");

    cursor.forEach(function(data) {
      insertDataInMongo(data);
    })
  }

  return deferred.promise;
}


function check(array, attr, value) {
  for (var i = 0; i < array.length; i += 1) {
    if (array[i][attr] === value) {
      return false;
    }
  }
  return true;
}

function get_value(array, attr) {
  for (var i = 0; i < array.length; i += 1) {
    if (array[i].hasOwnProperty(attr)) {
      return array[i][attr];
    }
  }
}


function getNames(token) {

  var deferred = q.defer();

  var MongoClient2 = require('mongodb').MongoClient;
  var url = 'mongodb://localhost/myDB';

  console.log("going to get Data");

  MongoClient2.connect(url, function(err, db) {
    if (err) return deferred.reject(new Error(err));
    console.log("connected for select");

    var data = db.collection('Details').find();
    var dataContext = [data, token, 0, 0, 0, 0, 0, 0, 0, null];

    deferred.resolve(dataContext);
  });
  return deferred.promise;
}


function convertDate(date) {
  var yyyy = date.getFullYear().toString();
  var mm = (date.getMonth() + 1).toString();
  var dd = (date.getDate() - 3).toString();

  var mmChars = mm.split('');
  var ddChars = dd.split('');

  return yyyy + '-' + (mmChars[1] ? mm : "0" + mmChars[0]) + '-' + (ddChars[1] ? dd : "0" + ddChars[0]);
}


authenticate()
  .then(getData)
  .then(insertDataInMongo)
  .then(getNames)
  .then(getMedia);

2 个答案:

答案 0 :(得分:0)

这应该有效。如果有任何问题,请告诉我。

function insertDataInMongo(a) {
  var deferred = q.defer();
  var MongoClient = require('mongodb').MongoClient;
  var url = 'mongodb://localhost/myDB';
  var token = a[1];
  MongoClient.connect(url, function(err, db) {
    if (err) return deferred.reject(new Error(err))
    console.log("connected for insert");

    var apiData = JSON.parse(a[0]).data;
    if (JSON.parse(a[0]).data) {
      db.collection('MediaData').insert(apiData, function(){
        console.log("Records Inserted");
        return deferred.resolve(token);
      });
    } else {
      db.collection('Details').drop(function(error, result){//Callback function that executes after drop operation has completed.
        if(error){
          return deferred.reject(error);//Reject the promise if there was an error
        }
        db.collection('Details').insert(JSON.parse(a[0]), function(err, res){//Callback function that executes after insert operation has completed.
          if(err){
            return deferred.reject(err);//Reject the promise if there was an error
          }
          console.log("Records Inserted");
          return deferred.resolve(token);
        });
      });
    }
  });
  return deferred.promise;
}

答案 1 :(得分:0)

从我从MongJDB的nodeJS驱动API看到的: https://mongodb.github.io/node-mongodb-native/api-generated/collection.html

提示:db.collection.drop是异步的,因此你必须使用回调

db.collection('Details').drop(function(err, result){
    // Do anything AFTER you dropped your collection
}

但由于你使用的是promises,你应该使用类似的东西:

authenticate()
.then(getData)
.then(db.collection('Details').drop)
.then(insertDataInMongo)
.then(getNames)
.then(getMedia);

或者如果你想真正保持相同的代码格式:

function dropCollectionInMongo() {
    db.collection('Details').drop()
}
authenticate()
.then(getData)
.then(dropCollectionInMongo)
.then(insertDataInMongo)
.then(getNames)
.then(getMedia);