【问题标题】:Function enters then before request completed函数在请求完成之前进入
【发布时间】:2018-07-24 17:12:18
【问题描述】:

我的异步函数在请求完成之前进入 then。 然后部分代码不应该只在异步功能完成后执行吗?如何在所有函数执行完毕后才调用函数?

app.js

var request_test = require('./request_test');

baseUrl = "https://github.com";
promiseFunction().then((result)=>{
    console.log("complete")
});

var promiseFunction = async function promiseFunction() {
    request_test.request_test(baseUrl);
}

request_test.js

var request = require('request');
var cheerio = require('cheerio');

var request_test = function check(baseUrl) {
    console.log("baseUrl:" + baseUrl)
     var options = {
        url: baseUrl
     };
     request(options, function (error, response, html) {
        if (!error) {
           console.log("no error");
        }else{
        console.log("else js");
        console.log(error);
        }
      });
 }

module.exports = {
    request_test: request_test
};

【问题讨论】:

  • async 没有检测完成的魔力。如果request_test.request_test(baseUrl); 是一个异步函数,那么它必须要么返回一个在异步操作完成时履行的承诺,要么它必须接受一个回调。如果它返回一个承诺,那么您可以从父函数返回该承诺,然后您可以在父函数上使用.then()。看来您期待promiseFunction() 神奇地知道request_test.request_test(baseUrl); 何时完成其异步操作。它不知道。
  • 相反,您需要让request_test.request_test(baseUrl); 返回一个与其异步操作相关联的承诺。然后,您可以从promiseFunction() 返回该承诺,然后promiseFunction().then() 将正常工作。
  • 不知道需要 promise 以确保 then 工作。在 request_test 模块中添加了 promise 并在 promiseFunction 中等待,它可以按需要工作。感谢您指出。

标签: node.js asynchronous request


【解决方案1】:

要使用then(),您需要返回promise。所以这里是一个很好的旧式promise 链的例子,只需从request_test 返回promise,一旦你解决或拒绝它,then() 将被调用:

promiseFunction().then((result) => {
  console.log("complete");
});

function promiseFunction() {
  return request_test();
}

function request_test() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      console.log("no error");
      resolve();
    }, 1000);
  });
}

或者也许使用现代方法 - async 方法来 await 调用返回 promise 的函数。

promiseFunction();

async function promiseFunction() {
  await request_test();
  console.log('complete');
}

function request_test() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      console.log("no error");
      resolve();
    }, 1000);
  });
}

您的问题来自 var request_test = function check(baseUrl) { ... 在此函数中您没有返回 promise,您甚至什么也没返回 :)

【讨论】:

  • 不知道需要 promise 以确保 then 工作。在 request_test 模块中添加了 promise 并在 promiseFunction 中等待以使用异步方法。它现在可以按需要工作。感谢您指出它和有用的代码。
  • 很高兴它对您有所帮助。干得好!
【解决方案2】:

如果您使用的是 async,我会继续使用 await/async 语法。此外,request 包不返回承诺,您可以使用request-promise-native 替代。承诺应该是你的辅助函数的返回值。它可能看起来像这样:

var request_test = require('./request_test');
var baseUrl = "https://github.com";

var promiseFunction = async function () {
  var result = await request_test.request_test(baseUrl);
  console.log("complete");
}

promiseFunction();

和模块:

var request = require('request-promise-native');
var cheerio = require('cheerio');

var request_test = function check(baseUrl) {
  console.log("baseUrl:" + baseUrl)
  var options = {
    url: baseUrl
  };

 return request(options).then(function (error, response, html) {
   if (!error) {
     console.log("no error");
   } else{
     console.log("else js");
     console.log(error);
   }
 });
}

module.exports = {
  request_test: request_test
};

【讨论】:

  • 操作问题是request_test.request_test(baseUrl); 返回什么。在不知不觉中,这只是一个疯狂的猜测。而且,事实上,没有理由使用await,因为如果它确实返回了一个承诺,那么该承诺就可以被返回。在这种情况下不需要async 或await。但是,它可能不会返回一个承诺,所以这才是真正的问题。与其胡乱猜测,不如找出事实,然后写出对这些事实的答案。你有足够的代表,我想你会知道的。
  • 它是一个节点包,假设request 会返回一个Promise(这是错误的,因为您需要使用request-promise-native 包装器)。不会认为这是一个如此疯狂的假设。我关于 await/async 的观点是,从风格上讲,坚持一种语法而不是混合两种语法更好。
  • 感谢您的包裹建议。稍后会调查它。至于这个问题,我没有意识到我需要承诺才能工作。为函数添加了 promise 并使用了异步方法。我选择了上一个答案,但也感谢您的帮助。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多