2015-08-08 2 views
0

У меня есть функция, которая создает объект базы данных из трех массивов. Массивы заполняются в каждом цикле, один из массивов полагается на значение в той же итерации цикла.Использование обещаний/обратных вызовов для ожидания завершения функции в javascript

Зависимый массив использует библиотеку requests и библиотеку cheerio для захвата строки для заполнения массива.

В настоящее время зависимый массив заполняется нулями, которые, как мне кажется, связаны с тем, что цикл не ожидает возврата запроса.

Я все еще участвую и хочу, чтобы это работало без прямого блокирования, чтобы сохранить асинхронность, поэтому я ищу обещания/обратные вызовы.

Это делается на стороне сервера, но из того, что я видел в документах cheerios, нет возможности обещать.

Вот что у меня есть. (getFile() - это функция, которая не заполняет массив «c», она также зависит от текущего значения, которое помещается в «b»). Я знаю, что функция getFile получает правильное значение с помощью теста журнала в консоли, поэтому проблема должна заключаться в реализации заполнения 'c'.

addToDB() - это функция, которая сохраняет значение в mongoDB, от тестирования я знаю, что объекты правильно помещаются в db, только массив 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()' является вашей операцией async. Если это так, то для того, чтобы помочь вам решить эту проблему, вам нужно будет показать этот код. Вот где должны произойти реальные изменения. – jfriend00

+0

addToDB - это просто функция, которая берет массивы, которые были заполнены и сохраняет их. Таким образом, он будет иметь: var objectToMake = new ... и затем сохранение ниже этого будет (через mongodb) objectToMake.save, async, который я считаю (все еще изучая js, не уверен, если это проблема) является массив c is не заполняется, то есть каждый цикл не ждет завершения getFile – user147910

+0

Где ваша операция async? Чего вы ждете, чтобы закончить? Ваш вопрос говорит о том, чтобы ждать чего-то, но не говорит, какую операцию ждать (и показать код для этой операции). Посылы помогают только решить проблему, если у вас есть операция async. В противном случае синхронные операции просто выполняются по порядку. – jfriend00

ответ

0

Прежде всего, вы должны понять, что любой процесс, который опирается, по крайней мере частично, на асинхронный подпроцесс, сам по себе является асинхронным.

На самом низком уровне кода на этот вопрос, в request() асинхронный, поэтому его вызывающий, getFile() является асинхронным, и его абонент, getInfo() также асинхронный.

Обещания - это абстракция результатов асинхронных процессов и чрезвычайно помогают в кодировании действий, которые необходимо предпринять, когда такие процессы завершаются - успешно или в случае сбоя.

Как правило, низкоуровневые асинхронные функции должны возвращать обещание, которым будут действовать их вызывающие абоненты, что в свою очередь вернет обещание своим абонентам и так далее вверх по стеке вызовов. Внутри каждой функции возвращенные обещания могут быть применены с использованием методов обещаний, главным образом .then(), и их можно агрегировать, используя, например, Promise.all() (синтаксис меняется).

В этом вопросе это не свидетельствует о том, что request() в настоящее время возвращает обещание. У вас есть три варианта:

  • узнайте, что request() действительно возвращает обещание.
  • rewrite request(), чтобы вернуть обещание.
  • написать функцию адаптера («обещающий»), который вызывает request(), и генерирует/возвращает обещание, которое позже выполняется или отклоняется в зависимости от результата request().

Первый или второй вариант был бы идеальным, но безопасное предположение для меня (Roamer) предполагает, что требуется адаптер. К счастью, я достаточно разбираюсь в вопросе, чтобы написать его. Cheerio, похоже, не включает реализацию обещаний jQuery, поэтому потребуется специальное обещание lib.

Вот функция адаптера, используя, используя синтаксис, который будет работать с Lib Bluebird или нативных 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() можно записать, чтобы сделать использование обещаний вернулся из самого низкого уровня-х адаптер.

Смежные вопросы