簡體   English   中英

如何在JavaScript中使用異步函數分配對象值

[英]How to assign object values using asynchronous functions in javascript

我正在建立一個javascript對象,其中一些值是由異步函數定義的。 我的問題是對象的定義速度比異步函數可以返回值的速度快:

    const array = ['a', 'b', 'c', 'd']
    const myArrayObj = [];

    function returnKey1 () {
        // make async call then store it in the return key1val:
        return key1val
    }

    function returnKey2 () {
        // make async call then store it in the return key2val:
        return key2val
    }

    function returnKey3 () {
        // make async call then store it in the return key3val:
        return key3val
    }

    _.forEach( array, function ( arr ) {
        myArrayObj.push({
            key1: returnKey1(), // returns undefined
            key2: returnKey2(), // returns undefined
            key3: returnKey3(), // returns undefined
      });

    });

有誰知道我應該做的正確方法? 提前致謝!

異步的性質是,如果要訪問異步過程的最終結果,則必須等待異步過程完成。

在您的情況下,您可以使用promise來實現此目標,而無需編寫很多代碼。

 // promise that resolves after 2 seconds const timeoutPromise = (str) => new Promise(resolve => setTimeout(() => resolve(str), 2000)); // functions that return promises that will eventually resolve to appropriate key values function returnKey1() { return timeoutPromise('key3'); } function returnKey2() { return timeoutPromise('key2'); } function returnKey3() { return timeoutPromise('key3'); } // helper function that returns a promise which will resolve with all the keys when all key-returning promises resolve function getKeys() { return Promise.all([ returnKey1(), returnKey2(), returnKey3() ]) } // usage getKeys().then((keys) => { console.log( keys[0], keys[1], keys[2] ); }); 

老式的方法是使用回調代替promise,promise具有更大的瀏覽器支持,但更為粗糙和原始。

注意:使用現代編譯器和/或Promise庫,您還可以獲得對Promise的廣泛瀏覽器支持。

 // function that calls its callback after 2 seconds const timeoutCallback = (cb, key) => setTimeout(() => cb(key), 2000); // functions that eventually call their callbacks with appropriate key values function returnKey1(cb) { return timeoutCallback(cb, 'key1'); } function returnKey2(cb) { return timeoutCallback(cb, 'key2'); } function returnKey3(cb) { return timeoutCallback(cb, 'key3'); } // helper function that calls its callback when all the keys are obtained function getKeys(cb) { let keys = [undefined, undefined, undefined]; let hasAllKeys = () => keys.every(key => typeof key === 'string'); function makeReturnKeyCallback(idx) { return (key) => { keys[idx] = key; if (hasAllKeys()) { cb(keys); } }; } returnKey1(makeReturnKeyCallback(0)); returnKey2(makeReturnKeyCallback(1)); returnKey3(makeReturnKeyCallback(2)); } // usage getKeys((keys) => { console.log( keys[0], keys[1], keys[2] ); }); 

無論您做什么,都會以諾言告終。 您可以直接使用Promise.all ,或者如果願意花費更多時間,可以為對象編寫自己的Promise.all版本。 最后,您可以使用async函數來完成此操作, async函數是一種以看起來像同步的方式編寫基於promise的代碼的方法。

使用Promise.all

 // Just examples for testing purposes. function returnKey1() { return promise(); } function returnKey2() { return promise(); } function returnKey3() { return promise(); } // Make a promise returning a random value after random time. function promise() { return new Promise(resolve => { const random = Math.random() * 1000; setTimeout(() => resolve(random), random); }); } // Wait for all promises to finish, then construct result. Promise.all([returnKey1(), returnKey2(), returnKey3()]) .then(([key1, key2, key3]) => ({key1, key2, key3})) .then(console.log); 

為對象編寫自己的Promise.all版本

我們還可以為對象創建Promise.all的類似物。 一些庫有這樣的例程。 我們將其稱為promiseAllKeys 我們將對象的每個屬性值傳遞給一個對象; 它返回一個已填充所有值的對象的Promise.all 。這為我們省去了將從Promise.all返回的數組轉換為所需對象的麻煩。

 function returnKey1() { return promise(); } function returnKey2() { return promise(); } function returnKey3() { return promise(); } function promise() { return new Promise(resolve => { const random = Math.random() * 1000; setTimeout(() => resolve(random), random); }); } // Convenience routine to construct an object from arrays of keys and values. function objectFromKeysAndValues(keys, values) { const result = {}; for (const i = 0; i < keys.length; i++) result[keys[i]] = values[i]; return result; } function promiseAllKeys(promises) { return Promise.all(Object.values(promises)) .then(values => objectFromKeysAndValues(Object.keys(promises), values)); } promiseAllKeys({key1: returnKey1(), key2: returnKey2(), key3: returnKey3()}) .then(console.log); 

使用async/await

您可以使用異步功能簡化代碼。 但是,編寫的這段代碼將等到每個諾言完成后再運行下一個諾言。

 function returnKey1() { return promise(); } function returnKey2() { return promise(); } function returnKey3() { return promise(); } function promise() { return new Promise(resolve => { const random = Math.random() * 1000; setTimeout(() => resolve(random), random); }); } async function makeObject() { return {key1: await returnKey1(), key2: await returnKey2(), key3: await returnKey3()}; } makeObject().then(console.log); 

簡單但混亂:

const array = ['a', 'b', 'c', 'd']
const myArrayObj = [];

function returnKey1 (cb) {
    // make async call then store it in the return key1val:
    cb ("key1val");
}

function returnKey2 (cb) {
    // make async call then store it in the return key2val:
   cb("key2val");
}

function returnKey3 (cb) {
    // make async call then store it in the return key3val:
    cb("key3val");
}

_.forEach( array, function ( arr ) {
    var o ={};

    returnKey1(function(key){
        o.key1=key;
      returnKey2(function(key){
        o.key2=key;
        returnKey3(function(key){
            o.key3=key
          myArrayObj.push(obj);
        })
      })
    })

  });

});

暫無
暫無

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

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