如何在Node/JavaScript中重写Promise

How to rewrite a Promise in Node / JavaScript

本文关键字:重写 Promise JavaScript Node      更新时间:2024-01-24

在另一个问题中-请参阅下面的[1]-我询问了如何迭代列表,并为该列表中的每个元素调用异步函数,最后使用累积结果列表。

用户tresdin[2]非常友好地指出了Node中的Promises。

他的榜样正是我想要的。又来了:

var request = require("request"),
    cheerio = require("cheerio"),
    base_url = "http://de.indeed.com/Jobs?q=";  // after equal sign for instance:   sinatra&l=
var Promise = require('promise');
var search_words = ["django", "python", "flask", 
                    "rails", "ruby",
                    "node", "javascript", "angularjs", "react",
                    "java", "grails", "groovy",
                    "php", "symfony", "laravel" ];

Promise.all(
    search_words.map( function(keyword) {  // map function on each element in search_words
        return new Promise( function(resolve, reject) {   // create a Promise instance for each element in search_words
            request( base_url + keyword + "&l=", function(err, resp, body) {
                if (err) {
                    return reject(err);
                }
                $ = cheerio.load(body);
                num = $("#searchCount")[0].children[0].data.split(" ").reverse()[0]; 
                resolve( [keyword, num] ); // will return value [keyword, num]
            }); // request( ... 
        }); // return new Promise(...)
    })  // map
) // Promise.all 
    .then( function(map_searchword) {
        console.log(map_searchword);
    }); // then

呼叫它将交付:

$ node promises_example.js
[ [ 'django', '139' ],
  [ 'python', '3.328' ],
  [ 'flask', '14' ],
  [ 'rails', '406' ],
  [ 'ruby', '1.061' ],
  [ 'node', '685' ],
  [ 'javascript', '9.169' ],
  [ 'angularjs', '1.164' ],
  [ 'react', '376' ],
  [ 'java', '19.100' ],
  [ 'grails', '47' ],
  [ 'groovy', '163' ],
  [ 'php', '4.978' ],
  [ 'symfony', '482' ],
  [ 'laravel', '110' ] ]

现在我的问题是:我能把迭代之外的"return new Promise"部分移到一个新函数中吗?

var request = require("request"),
    cheerio = require("cheerio"),
    base_url = "http://de.indeed.com/Jobs?q=";  // after equal sign for instance:   sinatra&l=
var Promise = require('promise');
var search_words = ["django", "python", "flask", 
                    "rails", "ruby",
                    "node", "javascript", "angularjs", "react",
                    "java", "grails", "groovy",
                    "php", "symfony", "laravel" ];

// moved "return new Promise()" out of iteration to a function
var do_request = function(keyword) {
    return new Promise( function(resolve, reject) {   // create a Promise instance for each element in search_words
        request( base_url + keyword + "&l=", function(err, resp, body) {
            if (err) {
                return reject(err);
            }
            $ = cheerio.load(body);
            num = $("#searchCount")[0].children[0].data.split(" ").reverse()[0]; 
            resolve( [keyword, num] ); // will return value [keyword, num]
        }); // request( ... 
    }); // return new Promise(...)
} // function
Promise.all(
    search_words.map( function(keyword) {  // map function on each element in search_words
        do_request(keyword);
    })  // map
) // Promise.all 
    .then( function(map_of_resolved_promises) {
        console.log(map_of_resolved_promises);
    }); // then

这将带来完全不同的结果:

$ node promises_example_2.js
[ undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined,
  undefined ]

有人能解释一下为什么这是不明确的吗?


[1] 异步函数上的迭代

[2]https://stackoverflow.com/users/3247703/tresdin

您需要添加一个return语句:

Promise.all(
    search_words.map( function(keyword) {  // map function on each element in search_words
        return do_request(keyword);
    })
)

或者你可以简单地做:

Promise.all(search_words.map(do_request))

map函数将直接将其参数(此处为关键字)传递给do_request方法。

您需要更换

search_words.map( function(keyword) { 
    do_request(keyword);
}) 

带有

search_words.map(do_request) 

search_words.map( function(keyword) { 
    return do_request(keyword);
}) 

在第一个示例中,从do_request返回的Promise没有传递给search_words.map回调。结果,返回undefined。这就是为什么您有一个undefined值的数组。

第二个例子相当于原始代码,而最后一个例子在每次迭代中都需要一个额外的回调。因此,它需要更多的内存。这意味着只有在循环中需要执行其他内容时,才应该使用最后一个解决方案。例如:

search_words.map( function(keyword) { 
    return do_request(keyword + 'something');
})