【问题标题】:How to call a helper function within a Promise'd function如何在 Promise 函数中调用辅助函数
【发布时间】:2019-02-06 15:27:21
【问题描述】:

我还是 Javascript 的新手,我希望有人可以帮助我解决我遇到的一个我无法解决的问题!

我有一个包含大量重复代码的函数,因此尝试将其拆分为辅助函数。但是,当我从 lMS 函数(当前称为 lMS(f).then()中调用辅助函数时,辅助函数会在依赖于 lMS 执行和完成的 init(g) 函数之后执行。

我 99% 确定我遇到了这个问题,因为我对 Promises 的工作方式和异步函数的性质有误解。

我尝试将重复的代码推送到一个单独的函数中,并在需要时调用它。我尝试将响应捕获为 Promises,或者将响应推送到数组中,然后仅在我返回所有项目时执行(与原始数组相比)。

以下是原始脚本,其中没有辅助函数,但有大量重复代码:https://github.com/willstocks-tech/dynamically-polyfill-features-for-a-script/releases/tag/0.0.5b5 - 第 57 行 (function loadMyScript(url))

我已将帮助代码放入 Codepen(我已经研究了几天)https://codepen.io/willstocks_tech/pen/pGgRrG?editors=1012

更新

在“辅助函数”代码中包含 init 函数和一个新笔,用于详细说明我根据反馈尝试/正在尝试的所有内容: https://codepen.io/willstocks_tech/pen/YBEzLW?editors=1012

当前代码:

function lMS(f) {
    if(Array.isArray(f)) {
        var urlen = f.length;
        for (var u = 0; u < urlen; u++) {
            var uri = f[u];
            if(uri !== null && uri !== '') {
                return new Promise(
                    function(resolve, reject) {
                        var thescript = document.createElement('script');
                        thescript.src = encodeURI(uri);
                        document.body.appendChild(thescript);
                        thescript.onerror = function(response) {
                            return reject("Loading the script failed!", response);
                        } 
                        thescript.onload = function() {
                            return resolve("Script setup and ready to load!");
                        } 
                    }
                )
            } else {
                return new Promise( //pretty sure this could just be Promise.resolve();
                    function(resolve, reject) {
                        return resolve ("No script to load");
                    }
                )
            }
        }
    } else {
        if(f !== null && f !== '') {
            return new Promise(
                function(resolve, reject) {
                    var thescript = document.createElement('script');
                    thescript.src = encodeURI(f);
                    document.body.appendChild(thescript);
                    thescript.onerror = function(response) {
                        return reject("Loading the script failed!", response);
                    } 
                    thescript.onload = function() {
                        return resolve("Script setup and ready to load!");
                    } 
                }
            )
        } else {
            return new Promise( //pretty sure this could just be Promise.resolve();
                function(resolve, reject) {
                    return resolve ("No script to load");
                }
            )
        }
    }
}

正在进行的新工作(使用助手):

function pL(e, f, g) {
    cNS(e).then(
        function() {
            lMS(f, g)
        }
    ).catch(function(error){return error})
    }
}

function lMS(f, g) {
    var w = [];
    if(Array.isArray(f)) {
        var urlen = f.length;
        for (var u = 0; u < urlen; u++) {
            var uri = f[u];
            if(uri !== null && uri !== '') {
                uriProm(uri); //go and get a script that is needed
                w.push(uri);  //maybe push to array and return resolve once everything is done?
            } else {
                return;
            }
        }
        if(w.length === url.length && w.every(function(value, index) { return value === url[index]})) {
            console.log("We've made it to here");
            return init(g) //go off to run a piece of code based reliant on the script of uriProm
            }
    } else { //not an array of values
        if(url !== null && url !== '') {
            uriProm(uri);
            return init(g)
        } else {
            return
        }
    }
}

//helper function (avoiding duplicate code)
function uriProm(uri){
    var thescript = document.createElement('script');
    thescript.src = encodeURI(uri);
    document.body.appendChild(thescript);
    thescript.onerror = function(response) {
        return reject("Loading the script failed!", response);
    } 
    thescript.onload = function() {
        return Promise.resolve();
    } 
}

    function init(g) {
        if(Array.isArray(g)) {
            var fnlen = g.length;
            for (var f = 0; f < fnlen; f++) {
                try {
                    new Function(g[f])();
                } catch(err) {
                    console.error('There was an error: ', err.name, err.stack);
                }
            }           
        } else {    
            try {
                new Function(g)();
            } catch(err) {
                console.error('There was an error: ', err.name, err.stack);
            }
        }
    }

【问题讨论】:

  • "很确定这可能只是 Promise.resolve();" - 确实是的
  • 在您当前的代码中,您 return 来自循环内的承诺,而不是将它们推送到某个 w 数组?请保持相同的功能
  • initpL 是什么,它们是从哪里来的?
  • 在您的辅助函数uriProm 中,您忘记了new Promise 行。不,您不能只在异步回调中放置 Promise.resolve()
  • @Bergi - 感谢您的及时回复!因此,我经历了各种迭代,包括您建议保留有前途的 uriProm,但同样的问题仍然存在 - 出于某种原因,uriProm 函数在 init 函数之后执行,最终导致失败。

标签: javascript promise helper


【解决方案1】:

经过几天的尝试和大量研究,我想出了如何做到这一点。

使用Array.forEach 遍历数组值(而不是尝试for 循环)意味着我可以将每个promise 推送到数组,然后将Promise.all 推送到数组上! :)

//This won't run in JSFiddle because the rest of the function doesn't exist
//https://github.com/willstocks-tech/dynamically-polyfill-features-for-a-script/releases - 0.0.5-beta.6

function lMS(f, g) {
  if (Array.isArray(f)) { //Check whether array is being passed or just string
    var promises = []; //Gotta catch 'em all... as an array
    f.forEach( //iterate through the array using Array.forEach()
      function(f) { //pass each item in the array through to the "get script" function
        promises.push(nbU(f)) //push the resolve/reject into the promises array
      }
    );
    Promise.all(promises) //Make sure that all promises that are returned come back as resolved
      .then( //then
        () => init(g) //run the init function!
      );
  } else if (!Array.isArray(f) && f !== null && f !== '') { //if not an array and not blank values
    return nonblankURL(f) //resolve or reject getting the script
      .then( //then
        () => init(g) //run the init function!
      )
  } else { //not array, blank values
    return init(g); //straight to init because no dependency (blank)
  }
}

我可以确认这正在按预期工作! https://codepen.io/willstocks_tech/pen/YBEzLW?editors=1012

我对 Promises/异步代码执行有了更多了解 :) 感谢 @Bergin 提供的所有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2015-07-22
    • 2015-01-28
    • 2017-04-27
    相关资源
    最近更新 更多