jQuery函数返回承诺

时间:2020-05-13 00:30:27

标签: javascript jquery promise

我有一个属于类别的对象(供参考的地板区域),该类别属于一种类型。添加新对象时,用户可以选择现有的或新的“类型”和“类别”。如果类别和/或类型不存在,则应创建一个新的类别。

对于UI,我有两个下拉列表,类型和类别,以及对象的属性。这些下拉菜单也可以添加新条目(使用select2)。选择现有类型时,“类别”下拉列表将使用该类型的“类别”重新填充。

如果选择了现有的Type,则应使用下拉列表中的现有typeId。如果是新类型,我们会请求创建一个新类型并返回新的typeId。然后,对类别执行相同的操作。然后,categoryId用于创建新对象。

我本质上知道实现此目标需要做什么。在实践中,我在如何格式化函数和返回的承诺方面有些挣扎。如果类型和类别都已经存在,我可以使它工作(下面的代码)。并进行一些更改,如果Type和Category都不存在,但两者都不存在,则使其正常工作。我知道这与将返回类型构造为函数的方式有关。

typeIdGet应该返回现有的或新的typeId,如果存在则返回一个Id,否则返回一个getJSON函数。

categoryIdGet应该执行相同的操作,但是如果需要新的Category,则使用先前返回的typeId。

在两种情况下,如何构造两个typeIdGet函数以返回ID?

如何构造两个categoryIdGet函数以从上一个函数获取返回的typeId并在两种情况下都返回一个ID?

<script>
// ... click event handler and some code to get the selected Type and Category ...

// code below handles the promises

var myTypeId, myCategoryId;

if (existingType) { // existing type, return the selected Id
    typeIdGet = $.when(Number(selectedTypeId)); // this is a promise that resolves immediately
} else { // new Type we need to create one and get the new Id
    typeIdGet = $.getJSON(
        "Dimensions/Create?handler=NewType",
        {
            floorAreaTypeName: selectedTypeOption.text()
        },
        function (response) { // returns new Id
            return Number(JSON.parse(response));
        }
    );
}

if (existingCategory) {
    categoryIdGet = $.when(Number(selectedCategoryId));
} else {
    categoryIdGet = $.getJSON(
        "Dimensions/Create?handler=NewCategory",
        {
            floorAreaTypeId: myTypeId, // this should be passed in
            floorAreaCategoryName: selectedCategoryOption.text()
        },
        function (response) { // returns new Id
            return Number(JSON.parse(response));
        }
    );
}

typeIdGet.then(function (typeId) {
    myTypeId = typeId;
    return categoryIdGet; // Can we not pass in the typeId here?
}).then(function (categoryId) {
    myCategoryId = categoryId;
    alert("myTypeId: " + myTypeId + " myCategoryId:" + myCategoryId);
    // Create new floor area here with the categoryId
}).fail("Something went wrong");

</script>

1 个答案:

答案 0 :(得分:1)

问题是(如您后面的评论中所暗示),这两个$.getJSON命令 并行运行,因为您没有做任何事情来等待第一个命令在运行第二个之前完成。

最简单的方法是将它们包装在函数中(并使函数始终返回一个使它们易于处理的承诺:

function typeIdGet() {
  if ( existingType ) return Promise.resolve( Number( selectedTypeId ) );
  return new Promise( function( resolve, reject ) {
    $.getJSON( `Dimensions/Create?handler=NewType`, {
      floorAreaTypeName : selectedTypeOption.text(),
    }, function( response ) {
      resolve( Number( JSON.parse( response ) ) );
    }
  } );
}

function categoryIdGet( typeId ) {
  if ( existingCategory ) return Promise.resolve( Number( selectedCategoryId ) );
  return new Promise( function( resolve, reject ) {
    $.getJSON( 'Dimensions/Create?handler=NewCategory', {
      floorAreaTypeId : typeId.
      floorAreaCategoryName : selectedCategoryOption.text(),
    }, function( response ) {
      resolve( Number( JSON.parse( response ) ) );
    } );
  } );
}

现在,您可以按照想要的顺序运行它们了:

typeIdGet().then( function( typeId ) {
  return categoryIdGet( typeId ).then( function( categoryId ) {
    console.log( "typeId:", typeId, "categoryId:", categoryId );
  } );
} );