簡體   English   中英

異步等待承諾

[英]Async await of a promise

我必須等待func1被定義為運行func2。 但由於func1 / 2/3包含承諾,因此它會在早期打印出“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是外部庫的功能

嘗試在承諾中包裝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")
  });
}

為了改進代碼, 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 resolvereject s。

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


獎金

如果你想要所有的promises (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';
  }
}

為了讓代碼工作,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
}

這個答案與Carl Edward的答案密切相關,但建立在node.js的約定之上。

非常不幸的是, promise_API_CALL()的回調不會先傳遞錯誤。 否則你可以使用util.promisify() 一種替代方法是遵循node.js的Custom promisified函數 它看起來像這樣:

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的新符號類型 應該意味着你就不會破壞對方。

這是一個完整的例子:

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")
}());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM