我在sails.js中遇到了一些异步事件的问题。
我正在从jsonapi中获取一些数据,并试图在for循环中将它们写入我的数据库。每件事都需要一个接一个地执行(按正确的顺序)。为了保持示例简单,让我们假设我正在尝试执行以下操作:

//let apiNames be a JSON that contains some names in that order: James, Betty, Jon
//let Customer be a DB which contains that names and related age

for(index in apiNames){
   console.log("Searching for "+apiNames[index].name+" in the Database...);
   Customer.find({name:apiNames[index].name}).exec(function(err,customerData){
      console.log("Found "+apiNames[index].name+" in the Database!");
      console.log(customerData);
   });
}

建议的日志应该如下所示:
Searching for James in the Database....
Found James in Database!
{name:James, age:23}

Searching for Betty in the Database....
Found Betty in Database!
{name:Betty, age:43}

Searching for Jon in the Database....
Found Jon in Database!
{name:Jon, age:36}

由于javascript是异步运行的,而db调用需要很长时间,因此输出如下:
Searching for James in the Database....
Searching for Betty in the Database....
Searching for Jon in the Database....
Found James in Database!
{name:James, age:23}
Found Betty in Database!
{name:Betty, age:43}
Found Jon in Database!
{name:Jon, age:36}

我已经尝试了几种方法来强制循环同步工作,但都没有成功。如果我调用exec内部的某个东西,它应该同步运行(通过与另一个exec链接),但我的问题是,它已经无法在循环中同步工作。有没有人能解决这个问题并能解释一下?
编辑:apinames不是数组,它是一个json,里面有一些数据。下面是apinames的外观示例:
[{
   "name": "James",
   "gender": "male"
},
{
   "name": "Betty",
   "gender": "female"
},
{
   "name": "Jon",
   "gender": "male"
}]

(添加了gender以在json中获得更多信息。这对解决方案并不重要)

最佳答案

由于apinames是一个对象,为了与ie9+兼容,我们可以使用object.keys()来获取对象中的键名,并使用它来迭代apinames

//process all names in the array one by one
function process(apiNames, keys) {
    //if there are no items in the array return from the function
    if (!keys.length) {
        return;
    }
    //get the first name in the array
    var key = keys.shift();
    var name = apiNames[key];
    console.log("Searching for " + name + " in the Database...");
    Customer.find({
        name: name
    }).exec(function (err, customerData) {
        console.log("Found " + name + " in the Database!");
        console.log(customerData);
        //once the current item is processed call the next process method so that the second item can be processed
        process(apiNames, keys);
    });
}

//call the process method with an array
var keys = Object.keys(apiNames);
process(apiNames, keys);

对于较旧的浏览器,使用polyfill添加对object.keys()的支持,如one provided by MDN
演示:Fiddle

08-07 15:08