Javascript for循环承诺

Javascript for loop Promises

本文关键字:承诺 循环 for Javascript      更新时间:2023-09-26

我有一个像这样的url数组

var urls = ["www.google.com", "www.yahoo.com"];

我想通过url循环并在循环内执行异步任务,而不是移动到下一个项目,直到异步任务完成。我知道你可以用承诺来做到这一点,但我在这方面遇到了一些麻烦。这里是

var xmlReader = require('cloud/xmlreader.js');
function readResponse_async(xlmString) {
    var promise = new Parse.Promise();
    xmlReader.read(xlmString, function (err, res) {
        if(err) {
            promise.reject(err);
        } else {
            promise.resolve(res);
        }
    });
    return promise;
}
for (i = 0; i < urls.length; i++) {
    Parse.Cloud.httpRequest({
        url: unionUrls[i],
    }).then(function(httpResponse) {
            try {
//              console.log(httpResponse.text)
                return readResponse_async(httpResponse.text)
            } catch (e) {console.log(e)}
}

但是现在它没有等待readResponse_async完成,我怎么能让它等待呢?

感谢

编辑

阅读响应后,我保存到我的数据库,我有另一个数组像这样

var location = ['USA', 'England'];

然后像这样保存

function saveLoc_async(data, location) {
var i3, i4, i5, m,
            TestItem = Parse.Object.extend("TestItem"),//can be reused within the loops?
            promise = Parse.Promise.as();//resolved promise to start a long .then() chain
        for (i3 = 0; i3 < data.count(); i3++) {
             (function(testItem) {
                        testItem.set("item", data.at(i));
                        testItem.set("location", location);
                        //build the .then() chain
                        promise = promise.then(function() {
                            return testItem.save();
                        });
                    })(new TestItem());
//************************
//CALL  retry(); here?
//**************************
}

因为有了你的回答我有

function retry() {
if (urlsUnion.length > 0) {
    var nextUrl = urlsUnion.pop();
    //********** ADDED LINE
    var nextLoc = location.pop();
    Parse.Cloud.httpRequest({
        url: nextUrl,
    }).then(function(httpResponse) {
        xmlReader.read(httpResponse.text, function (err, res) {
            if(err) {
                // show an error
            } else {
                //********** ADDED LINE
                saveLoc_async(res, nextLoc);
                retry();
            }
        });
    });
}
}

那么retry();应该去哪里,因为现在与保存有时它把第二个位置与第一项url之一?为什么会这样?

我为一个动画做了类似的事情。

var actions = [drawXXX, fadeOutYYY, drawXYZ];

this.startAnimation = function () {
    actions.reduce(function (previousAction, nextAction) {
        return previousAction.then(nextAction)
    }, $.when());
}

您的代码会立即触发这两个url,而不会在两者之间等待。

你要做的是从数组中删除第一个url并触发它。在'then'分支中检查数组中是否还有url,然后重复。

像这样(未经测试,编辑使代码再次干净):

var xmlReader = require('cloud/xmlreader.js');
function readResponse_async(xlmString) {
    xmlReader.read(xlmString, function (err, res) {
        if(err) {
            // show an error
        } else {
            readFirstUrl();
        }
    });
}
function readFirstUrl() {
    if (urlsUnion.length == 0) {
        return;
    }
    var url = urlsUnion.pop();
    Parse.Cloud.httpRequest({
        url: url,
    }).then(function(httpResponse) {
        readResponse_async(httpResponse.text);
    });
}
readFirstUrl();

我不确定我理解你使用的unionUrls数组,但如果你有你的URL在urls数组,我认为这是相当干净的:

function getUrl(url) {
      return Parse.Cloud.httpRequest(url)
                  .then( function(httpResponse) {
                     return readResponse_async(httpResponse.text);
                  });
}
urls.reduce( function(prev, url) {
   return prev ? prev.then( function() { getUrl(url); }) : getUrl(url);
 }, null);