迭代通常可与Map(),Set()..一起使用,但是会违反诺言

时间:2019-01-04 11:41:11

标签: javascript dictionary ecmascript-6 promise set

提供复制步骤。

const map = new Map()
let success = new Set()

let failed = new Set()
map.set('success', success)
map.set('failed', failed)
success.add(123)
failed.add(55)
success.add(456)

var iter = map.entries()
console.log(
  'printing map output ==> ',
  map,
  'map.entries() ==> ',
  map.entries(),
  'iter.next().value ==> ',
  iter.next().value,
  'iter.next().value ==> ',
  iter.next().value
)

for (const [key, value] of map.entries()) {
  for (const val of value) {
    console.log(key, val)
  }
}

上面的代码向我输出以下预期结果。

results WITHOUT PROMISE


所以现在,我使用一个承诺使用相同的代码,

$(button).submit(updateTags(enteredTags, tagName,contentIDs).then(
  (resultMap) => {
     console.log("result after promise ==> ", resultMap); // I get proper output here, please see the below image for this

       for (const [key, value] of resultMap.entries()) {
           for (const val of value) {
               console.log("key ==> ", key,"value ==> ", val)// I don't get all the results here.. I am hurting my head with this, did I do any mistake ?
           }
       }
  }));


  let updateTags = (newTags, tagName, contentIds) => {
    let deferred = Q.defer(),
        resultMap = new Map(),
        success_ids = [],
        failed_ids = [],
        counter = 1;
    resultMap.set("success", success_ids);
    resultMap.set("failed", failed_ids);

     contentIds.forEach(function (contentId) {
        var tags = [];
        osapi.jive.core.get({
            v: "v3",
            href: "/contents/" + contentId + ""
        }).execute(function (content) {
            tags = content.tags;
            content["tags"] = _.union(tags, newTags);
            osapi.jive.core.put({
                v: "v3",
                href: "/contents/" + contentId + "",
                body: content
            }).execute(function (response) {
                    if (response.error) {
                        failed_ids.push(contentId);
                    } else {
                        success_ids.push(contentId);
                    }
                    if (counter === contentIds.length) {
                        deferred.resolve(resultMap);
                        $("#spinner").hide()
                    }
                    counter++;
                    deferred.resolve(resultMap);
                }, function (error) {
                    failed_ids.push(contentId);
                    if (counter === contentIds.length) {
                        deferred.resolve(resultMap);
                        $("#spinner").hide()
                    }
                    counter++;
                }
            );
        })
    });
    return deferred.promise;
};

以下代码的输出图像: results with promise

最后,第二个代码段“带有承诺” 应该显示如下结果: enter image description here

我现在添加了我的所有代码,promise只解析了一次,我得到了resultMap来检查成功和失败的ID。我想对其进行迭代以再次将它们转储到记录器中。

1 个答案:

答案 0 :(得分:2)

在您当前问题中的代码中,您兑现承诺的时间过早:

let updateTags = (newTags, tagName, contentIds) => {
     //... removed some code that does not show where you go wrong
     contentIds.forEach(function (contentId) {
        osapi.jive.core.get()
        .execute(function (content) {
            }).execute(function (response) {
                    if (response.error) {
                        failed_ids.push(contentId);
                    } else {
                        success_ids.push(contentId);
                    }
                    if (counter === contentIds.length) {
                        deferred.resolve(resultMap);
                        $("#spinner").hide()
                    }
                    counter++;
                    //here you are always resolving the promise
                    deferred.resolve(resultMap);

我认为以下方法应该有效:

let updateTags = (newTags, tagName, contentIds) => {
    let deferred = Q.defer(),
        resultMap = new Map(),
        success_ids = [],
        failed_ids = [],
        counter = 1;
    resultMap.set("success", success_ids);
    resultMap.set("failed", failed_ids);
    //promise will never be resolved if you have no content ids
    if(contentIds.length === 0){
      //not sure if Q.resolve exist but here you return a resolved
      //  promise with the empty success and failed arrays
      $("#spinner").hide();
      return Promise.resolve(resultMap);//resolve with empty value
    }

     contentIds.forEach(function (contentId) {
        var tags = [];
        osapi.jive.core.get({
            v: "v3",
            href: "/contents/" + contentId + ""
        }).execute(function (content) {
            tags = content.tags;
            content["tags"] = _.union(tags, newTags);
            osapi.jive.core.put({
                v: "v3",
                href: "/contents/" + contentId + "",
                body: content
            }).execute(function (response) {
                    counter++;
                    if (response.error) {
                        failed_ids.push(contentId);
                    } else {
                        success_ids.push(contentId);
                    }
                    if (counter === contentIds.length) {
                        deferred.resolve(resultMap);
                        $("#spinner").hide()
                    }
                }, function (error) {
                    //I assume execute will either call one or the other function
                    // that is passed to it so increment counter here
                    counter++;
                    failed_ids.push(contentId);
                    if (counter === contentIds.length) {
                        deferred.resolve(resultMap);
                        $("#spinner").hide()
                    }
                }
            );
        })
    });
    return deferred.promise;
};