2015-08-08 174 views
0

我有一個函數可以創建三個數組中的一個數據庫對象。數組填充在每個循環中,其中一個數組依賴於循環的相同迭代中的值。使用承諾/回調等待功能在javascript中完成

依賴數組使用requests庫和cheerio庫來獲取一個字符串來填充該數組。

目前依賴數組填充空值,我認爲是因爲循環沒有等待請​​求返回。

我仍然在學習,並希望得到這個沒有直接阻斷工作,以保持異步的東西,所以我尋找到的諾言/回調。

這是服務器端完成的,但從我在cheerios文檔中看到的沒有承諾能力。

這是我到目前爲止。 (getFile()是不填充'c'數組的函數,它也取決於將當前值放入'b')。我知道getFile函數通過控制檯日誌測試獲得正確的值,所以問題必須在填充'c'的實現中。

addToDB()是保存一個值的MongoDB,從測試中我知道,對象是正確被放入一個數據庫中的功能,只是C數組是不正確的。

function getInfo(path) { 
    $(path).each(function(i,e) { 
    a.push(...) 
    b.push(value) 
    c.push(getFile(value)) 
    }) 
    var entry = new DB...//(a,b,c) 
    addToDB(entry); 
} 

function getFile(...) { 
    request(fullUrl, function (err, resp, page) { 
    if (!err && resp.statusCode == 200) { 
     var $ = cheerio.load(page); // load the page 
     srcEp = $(this).attr("src"); 
     return srcEp; 
    } // end error and status code 
    }); // end request 
} 

我一直在閱讀有關的承諾/回調,然後(),但我還沒有找到任何事情的作品。

+0

我假設'addToDB()'是你的異步操作的地方。如果是這樣,那麼對於我們來幫助你解決這個問題,你將不得不顯示該代碼。這就是真正需要改變的地方。 – jfriend00

+0

addToDB只是一個函數,它使用已經填充並保存的數組。所以它會有:var objectToMake = new ...然後保存在它下面(通過mongodb)objectToMake.save,異步我相信(仍然學習js,不知道這是否是問題)是數組c是沒有被填充,那就是每個循環都沒有等待getFile完成 – user147910

+0

你的異步操作在哪裏?你還等什麼完成?你的問題是等待某件事完成,但沒有說明要等待什麼操作(並顯示該操作的代碼)。如果您有異步操作,承諾只能幫助您解決問題。否則,同步操作只需按順序運行。 – jfriend00

回答

0

首先,你必須讓你的頭腦一輪的事實是,它依賴,至少部分地基於異步子過程中的任何過程,本身固有的異步的。

在此問題代碼的最低級別,request()是異步的,因此其調用者getFile()是異步的,其調用者getInfo()也是異步的。

承諾是異步進程的結果的抽象,並極大地幫助編碼應採取的行動,當這些過程完成 - 成功或失敗下。

通常情況下,低級別的異步函數應返回由他們的來電,這將反過來承諾返回調用者,依此類推,直到調用堆棧來採取行動的承諾。在每個函數內部,可以使用承諾方法對返回的承諾(主要是.then())採取行動,並且可以使用例如Promise.all()(語法變化)進行彙總。

在這個問題上,這是沒有證據表明request()返回當前的承諾。你有三個選擇:

  • 發現request()事實上確實返回一個承諾。
  • 重寫request()返回承諾。
  • 編寫一個調用request()的適配器函數(「promisifier」),並生成/返回承諾,稍後根據request()的結果完成或拒絕該承諾。

第一個或第二個選項是理想的,但對我來說(Roamer)的安全假設是假定需要一個適配器。幸運的是,我對這個問題足夠了解,可以寫出一個。 Cheerio似乎不包含jQuery的promise實現,所以需要一個專用的promise lib。

下面是一個適配器功能,使用語法將與藍鳥lib或本地JS承諾工作中使用:

//Promisifier for the low level function request() 
function requestAsync(url) { 
    return new Promise(function(resolve, reject) { 
     request(url, function(err, resp, page) { 
      if(err) { 
       reject(err); 
      } else { 
       if (resp.statusCode !== 200) { 
        reject(new Error('request error: ' + resp.statusCode)); 
       } 
      } else { 
       resolve(page); 
      } 
     }); 
    }); 
} 

現在getFile(...)getInfo()可以寫入利用的承諾,從最低級別的返回適配器。