使用promise等待被调用的函数并在继续之前完成它所做的事情

时间:2017-11-07 08:40:07

标签: javascript jquery es6-promise

我正在调用一个函数来加载一些文件,这个函数也是从其他地方调用的。

要成功运行此段代码searchconfig.js必须在

之前加载

我想要实现的是,对于此调用完成加载searchconfig.js然后继续使用其他代码,如果发生错误,请记录它:

loadRemoteFile("Search/" + Search.Configuration.PathToConfigurable + "/Configurable/searchconfig.js");

完整代码:

$(document).ready(function () { 
    if (Search.Configuration && Search.Configuration.PathToConfigurable) {
        // the file that is necessary for the code to run successfully
        loadRemoteFile("Search/" + Search.Configuration.PathToConfigurable + "/Configurable/searchconfig.js");
    }

    setTimeout(function () {

        // anchor for injecting the  results
        $('body').prepend("<div id='search-results' class='container'></div>")

        for (var configItem in tempConfig) {
            Search.Configuration[configItem] = tempConfig[configItem];
        }

        var configsToCheckForSlash = ["FullPathToConfigurableFolder", "pathToSearch", "PathToConfigurable", "SearchServiceURL", "ThumbnailsURL", "CMSThumbnailsURL", "PreviewBaseURL"];

        for (var x = 0; x < configsToCheckForSlash.length; x++) {
            Search.Configuration[configsToCheckForSlash[x]] = addForwardSlashToSearchConfigSettings(Search.Configuration[configsToCheckForSlash[x]]);
            _log(Search.Configuration[configsToCheckForSlash[x]])
        }

        for (var x = 0; x < Search.Configuration.pagesToAvoid.length; x++) {
            var pagesToAvoid = Search.Configuration.pagesToAvoid[x].toLowerCase();
            if (location.href.toLowerCase().indexOf(pagesToAvoid) > -1) {
                _log("Search loader abandoned. Please check settings if this is not intended.");
                return;
            }
        }

        $("head").append(Search.Configuration.requiredFiles);

        //pick implementation points  
        Search.Configuration.anchorToUseForMainSearch = $("#search-results");

        if (!Search.Configuration.anchorToUseForMainSearch.length) {
            _log("The search implementation could not find a suitable place to place the search, aborting.");
            return;
        }

        searchIsExpanded = false;
        writeSearchHTML();
    }, 400);
});

loadRemoteFile函数

function loadRemoteFile(filename, loadIntoHeader){ 
        filetype = filename.match(".css") ? "css" : "js";

        if (filetype=="js"){ 
            if(!loadIntoHeader){
                var script   = document.createElement("script");
                script.type  = "text/javascript";
                script.src   = filename;
                document.body.appendChild(script);          
            }else{
                ...             
            }           
        }else if (filetype=="css"){ 
            ...
        }
}

3 个答案:

答案 0 :(得分:1)

也许你想让loadRemoteFile返回一个Promise?

function loadRemoteFile(filename, loadIntoHeader){ 
    return new Promise(function(resolve, reject) {
        filetype = filename.match(".css") ? "css" : "js";

        if (filetype=="js"){ 
            if(!loadIntoHeader){
                var script   = document.createElement("script");
                script.type  = "text/javascript";
                script.src   = filename;
                script.onload = resolve;
                script.onerror = reject;
                document.body.appendChild(script);
            }else{
                // mystery code
            }           
        } else {
            // more mystery code
        }
    }
}

使用:

loadRemoteFile("Search/" + Search.Configuration.PathToConfigurable + "/Configurable/searchconfig.js").then(function() {
    // what to do on success
}).catch(function() {
    // what to do on failure
});

替代使用(这也使用上面的“promisified”loadRemoteFile

$(document).ready(function () {
    (async function() {
        // place **ALL** your code inside the IIFE inside .ready callback
        if (Search.Configuration && Search.Configuration.PathToConfigurable) {
            // the file that is necessary for the code to run successfully
            try {
                await loadRemoteFile("Search/" + Search.Configuration.PathToConfigurable + "/Configurable/searchconfig.js");
            } catch(error) {
                // do your error handling here
            }
        }
        // execution here starts after the above loadRemoteFile finishes
        // or the condition is false
    })();
});

答案 1 :(得分:0)

首先要做的事情是:loadRemoteFile函数需要返回对调用函数的承诺(或者你可以使用回调函数),以确保只有在loadRemoteFile完成加载脚本后才执行调用函数后脚本。所以,如下所示:

var filesList = {};

function loadRemoteFile(filename, callback) {
 if(filesList[filename]) {
  callback();
 }else {
  filesList[filename] = true;
  filetype = filename.match(".css") ? "css" : "js";

        if (filetype=="js"){ 
            if(!loadIntoHeader){
                var script   = document.createElement("script");
                script.type  = "text/javascript";
                script.src   = filename;
                script.onload = resolve;
                script.onerror = reject;
                document.body.appendChild(script);
            }else{
                // mystery code
            }           
        } else {
            // more mystery code
        }
  callback();
 }
}

现在,在您的函数中,始终使用回调函数调用loadRemoteFile函数

$(document).ready(function() {
 loadRemoteFile('config-file-path', function() {
 }
})

改进是检查请求文件的加载脚本列表,而不是维护文件名数组。但它只是代码优化的一部分;我希望这能给你这个想法。

答案 2 :(得分:0)

我最终使用的是等待文件加载。

我想要实现的是完成加载searchconfig.js,然后继续使用其他代码:

 function when_external_loaded(callback) {
        // means searchconfig.js is loaded,
        // we should restrict the number of times we check 
        // if the parameter exist or restrict the max time for checking it
        if (typeof x.pagesToAvoid === 'undefined') {
            setTimeout(function () {
                when_external_loaded(callback);
            }, 10); // wait 10 ms
        } else { callback(); }
    }

然后在:

(document).ready(function(){
    when_external_loaded(function () {
     // place all the code that you want to occur after the file has been loaded
    }
});

会发生什么是只有当x.pagesToAvoid !== 'undefined')表示已加载searchconfig.js时,我们才会加载函数调用回调函数。

请记住,你应该限制检查文件存在的时间,因为如果文件不存在,这将永远尝试(对我而言,它可以,因为文件的存在不依赖于什么,他将在那个地方)。

我没有使用promise解决方案,因为我误解了一些东西。如果发生,promise仅返回true,否则返回false。 所以当试图加载文件时(但它还没有加载到内存中)promise将是真的..这对我来说还不够。