简体   繁体   中英

Any way in JavaScript to avoid using setTimeout to execute a function right after another? Maybe with jQuery?

I'm using this code:

$newFilter = getNewFilter();

$fieldDropdown = getFieldDropdown(fieldData.field);
$newFilter.append($fieldDropdown);

$typeDropdown = getTypeDropdown($fieldDropdown.data('zenfilter').fieldId, $fieldDropdown.val(), fieldData.type);
$newFilter.append($typeDropdown);

$inputBox = getInputBox($typeDropdown.data('zenfilter').fieldId, $typeDropdown.data('zenfilter').fieldType, $typeDropdown.val(), fieldData.value);
$newFilter.append($inputBox);

And I get a error ( $fieldDropdown.data("zenfilter") is null ) on the fourth line ( $typeDropdown = getTypeDropdown... ). This is because the getFieldDropdown didn't finished execution yet. How can I call the functions lineally? Thanks a lot.

Edit: Added the getFieldDropdown function:

getFieldDropdown = function (populateData) {
    var $hiddenInput, i, $obj;

    $hiddenInput = $('<input>', {
        name: defaults.paramName + '[' + nFilters + '][field]',
        type: 'hidden'
    });
    $obj = $('<select></select>', {
        'class': classesHash.individualField,
        name: defaults.paramName + '[' + nFilters + '][fakefield]'
    }).
    data('zenfilter', { fieldId: nFilters }).
    addOption(fieldOptions).
    sortOptions(true).
    selectOptions('').
    change(function(){
        $(this).nextAll('select, div.' + classesHash.individualInputContainer).detach();
        $(this).removeClass(classesHash.incompleteField).after(getTypeDropdown($(this).data('zenfilter').fieldId, $(this).val()));
        $(this).prev('input[type=hidden]').val(defaults.data[$(this).val()].fieldname);
    });
    if (populateData) {
        for (i = 0; i < defaults.data.length; i += 1) {
            if (defaults.data[i].fieldname === populateData) {
                $obj.selectOptions(String(i));
            }
        }
    }

    return $hiddenInput.add($obj);
};

(addOptions, sortOptions and selectOptions are just a plugin's methods to manipulate selects easier, they don't do any AJAX)

I assume that getFieldDropdown is an asynchronous call, from your question (a definition for that function would make this question easier to answer).

JavaScript does execute in a single-threaded way; your problem is not that getFieldDropdown doesn't complete, your problem is that it initiates an asynchronous call and then returns. If you want to do work with the results of an asynchronous call, you have to provide that call a callback: a function to execute when it's done.

Assuming the callback is the second, currently un-provided argument to getFieldDropdown, you'd do something like this:

$fieldDropdown = getFieldDropdown(fieldData.field, function(){
    $newFilter.append($fieldDropdown);

    $typeDropdown = getTypeDropdown($fieldDropdown.data('zenfilter').fieldId,$fieldDropdown.val(), fieldData.type);
    $newFilter.append($typeDropdown);

    $inputBox = getInputBox($typeDropdown.data('zenfilter').fieldId,$typeDropdown.data('zenfilter').fieldType, $typeDropdown.val(), fieldData.value);
    $newFilter.append($inputBox);
});

that lets you defer the execution of the stuff that relies on the results of the asynchronous call until those results are there.

Those functions are called synchronously. What's most likely happening is that getFieldDropdown(fieldData.field) is returning null, or the object that it returns doesn't have the zenfilter property defined internally.

You will need to edit getFieldDropdown in order to achieve this. Instead of making it execute serially, it is better to re-design so that it can accept a callback method to run when execution is finished. This is the standard way with jQuery:

fieldDropdown = getFieldDropdown(fieldData.field, function () {

  $newFilter.append($fieldDropdown);

  $typeDropdown = getTypeDropdown($fieldDropdown.data('zenfilter').fieldId,   $fieldDropdown.val(), fieldData.type);
  $newFilter.append($typeDropdown);

  $inputBox = getInputBox($typeDropdown.data('zenfilter').fieldId,   $typeDropdown.data('zenfilter').fieldType, $typeDropdown.val(), fieldData.value);
  $newFilter.append($inputBox);

}
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM