asynchronous等待承诺
我必须等待func1才能运行func2。 但是由于func1 / 2/3包含承诺,它早打印“定期”。
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是一个外部库的function
尝试在一个承诺包装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'; } }
正如你所看到的,它使用try
和catch
来处理错误。 换句话说,如果其中一个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
,等待Promise
resolve
或reject
。 -
你可以使用多次,只要你喜欢 。
奖金 :
如果你想要所有你的promise (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的答案非常接近,但build立在node.js的约定上。
promise_API_CALL()
的callback不会首先传递错误,这真的很不幸。 否则,你可以使用util.promisify()
。 另一种方法是遵循node.js的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); }); }); };
我看到的唯一的问题是,这样做会改变原来的function(这不是你的,是一个粗鲁的坏习惯)。 但是这个问题稍微得到了缓解,因为它使用ES6的新符号types ,这意味着你不会互相打破。
这是一个完整的例子:
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") }());