用 Promises 返回的数据替换出现的文本

Replace text occurrences with data returned by Promises

我有一个博客-post是这样的:

var post ="## Cool Post [embed]https://soundcloud.com/wonnemusik/teaser-schotone-dear-thomson-button-remix[/embed]"
+ "Here comes another one  [embed]https://soundcloud.com/straightech-bonn-podcast/straightech-and-friends-7-oscar-ozz[/embed]";

现在,对于 [embed]soundcloud-url[/embed] 的每次出现,我都需要调用他们的 API 端点 http://api.soundcloud.com/resolve.json?url=soundcloud-url&client_id=my-id,解析返回的 JSON 并将 [embed] 替换为我的自己的标记。

我如何通过 Promises 使用它?

var post ="## Cool Post [embed]https://soundcloud.com/wonnemusik/teaser-schotone-dear-thomson-button-remix[/embed]"
+ "Here comes another one  [embed]https://soundcloud.com/straightech-bonn-podcast/straightech-and-friends-7-oscar-ozz[/embed]"
var re = /\[embed\](.*)\[\/embed\]/gm;
var m;

do {
    m = re.exec(post);
    if (m) {
      var apiCallUrl = "http://api.soundcloud.com/resolve.json?url=" + m[1] '&client_id=...'
      request(apiCallUrl).then(function(body) {
        var trackinfo = JSON.parse(body[0].body)
        return trackinfo.title
     }
    }
} while (m);

// have all promises fulfilled and old embed in post-var replaced

我没有具体使用 bluebird,但通常有 an all method that wraps an array of promises (or takes promises as arguments). A glance at the API documentation for bluebird shows they do have an all 方法供您使用。您需要在 do/while 循环中创建一个 promises 数组,然后在末尾调用 all

var resultPromises = [];
var m;
do {
    m = re.exec(post);
    if (m) {
        var apiCallUrl = "http://api.soundcloud.com/resolve.json?url=" + m[1] '&client_id=...'
        resultPromises.push(request(apiCallUrl));
    }
} while (m);

// have all promises fulfilled and old embed in post-var replaced
Promise.all(resultPromises).then(function (results) {
    // do stuff.
});

现在,如果您想用承诺的结果替换原始文本,您还需要将匹配项存储在一个数组中。 thenresults 参数将是一个响应数组,按照它们最初添加到数组中的顺序排列。所以,你可以这样做:

var resultPromises = [];
var matches = [];
var m;
do {
    m = re.exec(post);
    if (m) {
        var apiCallUrl = "http://api.soundcloud.com/resolve.json?url=" + m[1] '&client_id=...'
        resultPromises.push(request(apiCallUrl));
        matches.push(m);
    }
} while (m);

var i = 0;
// have all promises fulfilled and old embed in post-var replaced
Promise.all(resultPromises).then(function (results) {
    // haven't tested this. Will leave as practice for the OP :)
    post = post.replace(matches[i], results[i].body[0].body.title);
    i += 1;
});

您可以使用处理异步回调的this replace function

var post = "## Cool Post [embed]https://soundcloud.com/wonnemusik/teaser-schotone-dear-thomson-button-remix[/embed]"
         + "Here comes another one  [embed]https://soundcloud.com/straightech-bonn-podcast/straightech-and-friends-7-oscar-ozz[/embed]"
var re = /\[embed\](.*)\[\/embed\]/gm;

return replaceAsync(post, re, function(m, url) {
     var apiCallUrl = "http://api.soundcloud.com/resolve.json?url=" + url + '&client_id=…'
     return request(apiCallUrl).then(function(res) {
         return JSON.parse(res[0].body).title;
     });
});