异步等待承诺

时间:2017-11-30 17:47:39

标签: javascript node.js promise

我必须等待func1被定义为运行func2。但由于func1 / 2/3包含promises,因此它会在早期打印出“termined”。

async function executeAsyncTask () {
              const res1 = await func1(a,b,c)
              const res2 = await func2(a,b,c)
              const res3 = await func2(a,b,c)

              return console.log(res1 , res2 , res3 )
            }

executeAsyncTask ()

func1的

class A{

    promise_API_CALL(params){
      //some code here..
    }

    func1(a,b,c){

    //so work here...

    this.promise_API_CALL(params, function( data, err ) {
       if(err){console.error(err)}
      console.log( data );
      return data;
    });

    //so work here...
    console.log("termined")


}

编辑:promise_API_CALL是外部库的功能

4 个答案:

答案 0 :(得分:4)

尝试在承诺中包装api调用。否则我无法看到它按照你想要的方式工作:

func1(a, b, c) {
  return new Promise((resolve, reject) => {
    this.promise_API_CALL(params, function(data, err) {
      if (err) {
        console.error(err)
        reject(err);
      }

      console.log(data);
      resolve(data);
    });

    //so work here...
    console.log("termined")
  });
}

答案 1 :(得分:1)

为了改进您的代码,executeAsyncTask的定义应如下所示:

async function executeAsyncTask () {
  try {

    const res1 = await func1(a,b,c)
    const res2 = await func2(a,b,c)
    const res3 = await func3(a,b,c)

    return [res1, res2, res3]; // Return all values from 'each await' as an array

  } catch (err) {
      throw 'Promise Rejected';
  }
}

如您所见,它甚至使用trycatch来处理错误。换句话说,如果其中一个await函数为rejected,则catch会自动抛出错误。

// This 'func1 code' from 'Carl Edwards' is the same
func1(a, b, c) {
  return new Promise((resolve, reject) => {
    promise_API_CALL(params, function(data, err) {
      if (err) {
        console.error(err)
        reject(err);
      }

      console.log(data);
      resolve(data);
    });

    //so work here...
    console.log("termined")
  });
}

最后你像这样打电话给executeAsyncTask

executeAsyncTask().then(function(result) {
    console.log("result => " + result); // Result of 'res1, res2, res3'
}).catch(function(error) {
    console.log("error => " + error); // Throws 'Promise Rejected'
});

请记住:

  • 每个async函数都会返回Promise个对象await语句在Promise上运行,等到Promise resolve s或reject s。

  • 您可以根据需要多次使用await

<强>奖金

如果您希望所有承诺(func1, func2, func3)并行执行(不是一个接一个),您可以像这样修改executeAsyncTask函数:

async function executeAsyncTask () {
  try {

    return [ res1, res2, res3 ] = await Promise.all([
        func1(a,b,c),
        func2(a,b,c),
        func3(a,b,c)
    ])

  } catch (err) {
      throw 'Promise Rejected';
  }
}

答案 2 :(得分:0)

为了让代码工作,func1必须是这样的:

async func1(a,b,c){
    const res = await promise_API_CALL(params, function( data, err ) {
       if(err){console.error(err)}
      console.log( data );
      return data;
    });

    console.log("termined");
    return res;
}

然后运行它将起作用

async function executeAsyncTask () {
  const res1 = await func1(a,b,c);
  const res2 = await func2(a,b,c);
  const res3 = await func2(a,b,c);
  //yada yada yada
}

答案 3 :(得分:0)

这个答案与Carl Edward's answer密切相关,但建立在node.js&#39;之上。约定。

真的很遗憾,promise_API_CALL()的回调并没有首先传递错误。否则你可以使用util.promisify()。一种替代方案是遵循node.js&#39; Custom promisified functions。它看起来像这样:

const util = require("util");

promise_API_CALL[util.promisify.custom] = function (params) {
    return new Promise((resolve, reject) => {
        promise_API_CALL(params, function (data, err) {
            if (err) {
                return reject(err);
            }
            resolve(data);
        });
    });
};

我看到的唯一问题是这样做会改变原来的功能(这不是你的,并且有点粗鲁坏习惯)。但问题略有减轻,因为它使用的是ES6的新Symbol type 意味着你不会互相诅咒。

这是一个完整的例子:

const util = require("util");

/**
 * Use to force the API along the failure path
 * @constant {Boolean}
 */
const SHOULD_FAIL = false;

/**
 * Callback to deal with API responses
 * @callback apiCallback
 * @param {Object} data The data of the response
 * @param {Error} [err] Optional error that says something went wrong
 */

/**
 * Dummy API calling function
 * @param {Object} kwargs api arguments
 * @param {apiCallback} cb The callback that handles the response
 */
function apiCall(kwargs, cb) {
    setTimeout(() => {
        // Allow testing of failure path
        if (SHOULD_FAIL) {
            return cb(undefined, new Error("Purposefull failure"));
        }
        // Success path
        cb({
            foo: "bar"
        });
    }, 1000);
}

/*
 * Create a function that wraps the apiCall function in a Promise
 * and attach it to apiCall's util.promisify.custom Symbol
 */
apiCall[util.promisify.custom] = function (kwargs) {
    return new Promise((resolve, reject) => {
        apiCall(kwargs, (data, err) => {
            if (err) {
                return reject(err);
            }
            resolve(data);
        });
    });
};

// Create shorthand function to the promisified function
const asyncApiCall = util.promisify(apiCall);

// Sanity check to make sure that they are the same
console.log(`Are promisifies the same? ${asyncApiCall === apiCall[util.promisify.custom]}`);

// Run tester function
(async function main() {
    // Do some stuff
    console.log("Started");

    // Use the async func
    let some_data_from_api;
    try {
        some_data_from_api = await asyncApiCall({
            fizz: "buzz"
        });
    } catch (err) {
        console.error(err);
    }

    // Print the data after we have it
    console.log(some_data_from_api);

    //so work here...
    console.log("Done")
}());