【问题标题】:Async load inside replace function异步加载内部替换功能
【发布时间】:2015-02-10 23:23:57
【问题描述】:

我正在使用 Javascript 进行替换。我做了这样的事情:

var replacedText = originalText.replace(regex, function(value, i) { 
    return value + 'some_additional_data';
});

return replacedText;

但是现在我需要在 replace 方法中加载一个 HTML 模板。 load方法是这样调用的:

res.render(location, json, function(error, html) {
    //i have the html loaded with my json data
});

我需要在我的替换方法中加载它,但我无法做到:

var replacedText = originalText.replace(media, function(value, i) {
    var json = buildJSON(value);
    res.render(location, json, function(error, html) {
        //how could i return the "html" object for the replace function?
    });
});

我尝试过类似的方法,但没有成功:

var replacedText = originalText.replace(media, function(value, i) {
    var json = buildJSON(value);
    return res.render(location, json, function(error, html) {
        return html;
    });
});

任何帮助将不胜感激 提前非常感谢您

【问题讨论】:

  • 你想做的事是不可能的。你知道函数异步意味着什么吗?
  • 是的,我想...我会以不同的方式来做。谢谢
  • @FelixKling,我终于在way shown by jfriend00 中做到了。两步解决方案。

标签: javascript asynchronous replace callback


【解决方案1】:

当您有一个需要同步返回值的回调时,您不能在该回调中使用异步操作来获取该值。异步操作(根据定义)将在回调返回后的某个时间后完成,因此异步操作的结果无法从回调中返回,并且无法让 JS 等待异步操作。

我并没有完全按照您的代码尝试执行的操作,但从您的话来看,听起来您想加载一个 HTML 模板并在替换操作中使用它。有一些不同的方法可以解决这个问题。

例如,您可以通过两次传递来做到这一点。

  1. 第一遍实际上并没有改变你的字符串,它只是构建了一个需要的模板列表。

  2. 然后,加载该列表中的所有模板。

  3. 然后,当您需要的所有模板都加载完毕后,您就可以进行替换,使用已加载的模板进行您计划的同步替换。

【讨论】:

  • 这种方法对我有用!这比我想象的要容易。非常感谢!
【解决方案2】:

不,replace 只支持同步回调。但是,这里有一个通用函数,它接受一个产生承诺的回调,并为所有替换的字符串返回一个承诺:

function replaceAsync(str, re, callback) {
    // http://es5.github.io/#x15.5.4.11
    str = String(str);
    var parts = [],
        i = 0;
    if (Object.prototype.toString.call(re) == "[object RegExp]") {
        if (re.global)
            re.lastIndex = i;
        var m;
        while (m = re.exec(str)) {
            var args = m.concat([m.index, m.input]);
            parts.push(str.slice(i, m.index), callback.apply(null, args));
            i = re.lastIndex;
            if (!re.global)
                break; // for non-global regexes only take the first match
            if (m[0].length == 0)
                re.lastIndex++;
        }
    } else {
        re = String(re);
        i = str.indexOf(re);
        parts.push(str.slice(0, i), callback.apply(null, [re, i, str]));
        i += re.length;
    }
    parts.push(str.slice(i));
    return Promise.all(parts).then(function(strings) {
        return strings.join("");
    });
}

【讨论】:

  • 使用 Promise 的非常好的解决方案,如果有人不能使用 Promise,它可以很容易地修改为不使用 Promise 的版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-25
  • 2021-11-28
  • 2021-07-16
  • 2018-03-30
  • 2019-01-02
相关资源
最近更新 更多